<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://switchbrew.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Yellows8</id>
	<title>Nintendo Switch Brew - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://switchbrew.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Yellows8"/>
	<link rel="alternate" type="text/html" href="https://switchbrew.org/wiki/Special:Contributions/Yellows8"/>
	<updated>2026-05-08T03:27:28Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14682</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14682"/>
		<updated>2026-05-07T20:42:55Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+] [[#GetTransferEventId|GetTransferEventId]]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func. This handles initializing the contents of the fs file used with [[#GetList|GetList]] with the output of [[Filesystem_services|FindSaveDataWithFilter]] with SaveDataSpaceId = User. A state field is also updated.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output [[Network|transfer_event_id]] from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#GetList|GetList]] and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== GetTransferEventId ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads the [[#RequestServerProfile|transfer_event_id]] from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func. This essentially loops through the fs data also used by [[#GetList|GetList]], using [[NS_services|IApplicationManagerInterface DeleteSaveData]] with each entry (with the SaveDataId field from the entry and SaveDataSpaceId = User).&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call the same savedata-deletion func as [[#CompleteAsync|CompleteAsync]].&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#GetList|GetList]].&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || [[#GetList|GetList]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || Uuid (from &amp;lt;code&amp;gt;nn::util::GenerateUuid()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || ApplicationIdsCount (arraycount from [[#Cmd1110]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x8 || ApplicationId (first ApplicationId from the input array)&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x8 || [[Network|transfer_event_id]] from the [[#PrepareAsync|/start]] request, then used with the remaining network requests.&lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x134 || 0x10 || Zeros with savedata.&lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The Uuid must be non-zero.&lt;br /&gt;
* The ApplicationIdsCount must be 0x1-0x800.&lt;br /&gt;
* The ApplicationId must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== GetList ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Initial response payload, after the header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the data payload with the above size.&lt;br /&gt;
&lt;br /&gt;
This is used for transferring the contents of a fs file (server reads from it, client writes to a file).&lt;br /&gt;
&lt;br /&gt;
With savedata this is an array where each entry is 0x50-bytes, where each entry has the structure (converted from [[Filesystem_services#SaveDataInfo|SaveDataInfo]]):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Type: 0 = SaveDataType System, 1 = SaveDataType Account, 2 = SaveDataType Device.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || IsAccountIdValid (whether loading the AccountId was successful when UserId is non-zero)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || Output from sdk func &amp;lt;code&amp;gt;nn::fs::QuerySaveDataRequiredSizeForImport&amp;lt;/code&amp;gt; (on NX the input PlatformIdForSaveDataSizeCalculation is 1).&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || SaveDataId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x10 || UserId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x8 || AccountId ([[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId with the UserId, when loaded successfully where UserId is set)&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x8 || ApplicationId (for System, SystemSaveDataId)&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || 0x4 || [[NS_services#IApplicationVersionInterface|LaunchRequiredVersion]] (from GetLaunchRequiredVersion, for Account/Device)&lt;br /&gt;
|-&lt;br /&gt;
| 0x38 || 0x18 || [[OLSC_services#UserSaveDataProperty|UserSaveDataProperty]], from GetUserSaveDataProperty. Only with Account. If IsAccountIdValid is not set this is cleared instead.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Filesystem_services|GetSaveDataCommitId]] is also used when initializing the above entry, however the output is unused besides returning the Result on failure.&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14681</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14681"/>
		<updated>2026-05-06T16:06:21Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+] [[#GetTransferEventId|GetTransferEventId]]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func. This handles initializing the contents of the fs file used with [[#GetList|GetList]] with the output of [[Filesystem_services|FindSaveDataWithFilter]] with SaveDataSpaceId = User. A state field is also updated.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output [[Network|transfer_event_id]] from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#GetList|GetList]] and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== GetTransferEventId ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads the [[#RequestServerProfile|transfer_event_id]] from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#GetList|GetList]].&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || [[#GetList|GetList]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || Uuid (from &amp;lt;code&amp;gt;nn::util::GenerateUuid()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || ApplicationIdsCount (arraycount from [[#Cmd1110]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x8 || ApplicationId (first ApplicationId from the input array)&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x8 || [[Network|transfer_event_id]] from the [[#PrepareAsync|/start]] request, then used with the remaining network requests.&lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x134 || 0x10 || Zeros with savedata.&lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The Uuid must be non-zero.&lt;br /&gt;
* The ApplicationIdsCount must be 0x1-0x800.&lt;br /&gt;
* The ApplicationId must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== GetList ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Initial response payload, after the header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the data payload with the above size.&lt;br /&gt;
&lt;br /&gt;
This is used for transferring the contents of a fs file (server reads from it, client writes to a file).&lt;br /&gt;
&lt;br /&gt;
With savedata this is an array where each entry is 0x50-bytes, where each entry has the structure (converted from [[Filesystem_services#SaveDataInfo|SaveDataInfo]]):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Type: 0 = SaveDataType System, 1 = SaveDataType Account, 2 = SaveDataType Device.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || IsAccountIdValid (whether loading the AccountId was successful when UserId is non-zero)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || Output from sdk func &amp;lt;code&amp;gt;nn::fs::QuerySaveDataRequiredSizeForImport&amp;lt;/code&amp;gt; (on NX the input PlatformIdForSaveDataSizeCalculation is 1).&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || SaveDataId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x10 || UserId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x8 || AccountId ([[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId with the UserId, when loaded successfully where UserId is set)&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x8 || ApplicationId (for System, SystemSaveDataId)&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || 0x4 || [[NS_services#IApplicationVersionInterface|LaunchRequiredVersion]] (from GetLaunchRequiredVersion, for Account/Device)&lt;br /&gt;
|-&lt;br /&gt;
| 0x38 || 0x18 || [[OLSC_services#UserSaveDataProperty|UserSaveDataProperty]], from GetUserSaveDataProperty. Only with Account. If IsAccountIdValid is not set this is cleared instead.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Filesystem_services|GetSaveDataCommitId]] is also used when initializing the above entry, however the output is unused besides returning the Result on failure.&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14680</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14680"/>
		<updated>2026-05-06T15:18:09Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+] [[#GetTransferEventId|GetTransferEventId]]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#GetList|GetList]] and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== GetTransferEventId ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads the [[#RequestServerProfile|transfer_event_id]] from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#GetList|GetList]].&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || [[#GetList|GetList]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || Uuid (from &amp;lt;code&amp;gt;nn::util::GenerateUuid()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || ApplicationIdsCount (arraycount from [[#Cmd1110]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x8 || [[Network|transfer_event_id]] from the [[#PrepareAsync|/start]] request, then used with the remaining network requests.&lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x134 || 0x10 || Zeros with savedata.&lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The Uuid must be non-zero.&lt;br /&gt;
* The ApplicationIdsCount must be 0x1-0x800.&lt;br /&gt;
* The ApplicationId must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== GetList ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Initial response payload, after the header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the data payload with the above size.&lt;br /&gt;
&lt;br /&gt;
This is used for transferring the contents of a fs file (server reads from it, client writes to a file).&lt;br /&gt;
&lt;br /&gt;
With savedata this is an array where each entry is 0x50-bytes, where each entry has the structure (converted from [[Filesystem_services#SaveDataInfo|SaveDataInfo]]):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Type: 0 = SaveDataType System, 1 = SaveDataType Account, 2 = SaveDataType Device.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || IsAccountIdValid (whether loading the AccountId was successful when UserId is non-zero)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || Output from sdk func &amp;lt;code&amp;gt;nn::fs::QuerySaveDataRequiredSizeForImport&amp;lt;/code&amp;gt; (on NX the input PlatformIdForSaveDataSizeCalculation is 1).&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || SaveDataId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x10 || UserId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x8 || AccountId ([[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId with the UserId, when loaded successfully where UserId is set)&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x8 || ApplicationId (for System, SystemSaveDataId)&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || 0x4 || [[NS_services#IApplicationVersionInterface|LaunchRequiredVersion]] (from GetLaunchRequiredVersion, for Account/Device)&lt;br /&gt;
|-&lt;br /&gt;
| 0x38 || 0x18 || (only with Account when IsAccountIdValid is set)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Filesystem_services|GetSaveDataCommitId]] is also used when initializing the above entry, however the output is unused besides returning the Result on failure.&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14675</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14675"/>
		<updated>2026-05-05T01:12:05Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+] [[#GetTransferEventId|GetTransferEventId]]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== GetTransferEventId ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads the [[#RequestServerProfile|transfer_event_id]] from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || Uuid (from &amp;lt;code&amp;gt;nn::util::GenerateUuid()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || ApplicationIdsCount (arraycount from [[#Cmd1110]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x8 || [[Network|transfer_event_id]] from the [[#PrepareAsync|/start]] request, then used with the remaining network requests.&lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x134 || 0x10 || Zeros with savedata.&lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The Uuid must be non-zero.&lt;br /&gt;
* The ApplicationIdsCount must be 0x1-0x800.&lt;br /&gt;
* The ApplicationId must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Network&amp;diff=14674</id>
		<title>Network</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Network&amp;diff=14674"/>
		<updated>2026-05-04T21:55:15Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* transfer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page documents DNS domains and lists information relevant to the online services used by the Switch.&lt;br /&gt;
&lt;br /&gt;
= Domains =&lt;br /&gt;
Only HTTPS is used with these domains unless noted otherwise.&lt;br /&gt;
&lt;br /&gt;
== CDN ==&lt;br /&gt;
The URLs for content delivery network servers on the Switch usually follow this format:&lt;br /&gt;
 {server_name}.hac.{environment}.{serverset}.{host}&lt;br /&gt;
&lt;br /&gt;
Where:&lt;br /&gt;
 {server_name}: One of the registered server names.&lt;br /&gt;
 {environment}: &amp;quot;dp1&amp;quot;, &amp;quot;lp1&amp;quot;, &amp;quot;sp1&amp;quot;, &amp;quot;dd1&amp;quot;, &amp;quot;jd1&amp;quot;, &amp;quot;sd1&amp;quot;, &amp;quot;td1&amp;quot; or &amp;quot;xd1&amp;quot;.&lt;br /&gt;
 {serverset}: &amp;quot;eshop&amp;quot; (online shop), &amp;quot;d4c&amp;quot; (content delivery) or &amp;quot;dragons&amp;quot; (online membership).&lt;br /&gt;
 {host}: &amp;quot;nintendo.net&amp;quot; (global cdn), &amp;quot;n.nintendoswitch.cn&amp;quot; (chinese cdn).&lt;br /&gt;
&lt;br /&gt;
=== Servers ===&lt;br /&gt;
* &amp;quot;[[#sun|sun.hac.%.d4c.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;[[#aqua|aqua.hac.%.d4c.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;[[#atum/atumn|atum.hac.%.d4c.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;[[#atum/atumn|atumn.hac.%.d4c.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;atumn-dummy.hac.%.d4c.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;[[#superfly|superfly.hac.%.d4c.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;bugyo.hac.%.eshop.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;[[#beach|beach.hac.%.eshop.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;pushmo.hac.%.eshop.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;[[#tagaya|tagaya.hac.%.eshop.nintendo.net]]&amp;quot;&lt;br /&gt;
* [5.0.0+] &amp;quot;[[#pearljam|pearljam.hac.%.eshop.nintendo.net]]&amp;quot;&lt;br /&gt;
* [6.0.0+] &amp;quot;dragons.hac.%.dragons.nintendo.net&amp;quot;&lt;br /&gt;
* [6.0.0+] &amp;quot;dragonst.hac.%.dragons.nintendo.net&amp;quot;&lt;br /&gt;
* [6.0.0+] &amp;quot;[[#tigers|tigers.hac.%.dragons.nintendo.net]]&amp;quot;&lt;br /&gt;
* [14.0.0+] &amp;quot;[[#veer|veer.hac.%%.d4c.nintendo.net]]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== sun ====&lt;br /&gt;
Used for checking whether a sysupdate is available. Equivalent to NetUpdateSOAP from past systems.&lt;br /&gt;
&lt;br /&gt;
[[NIM_services|NIM]] sends a HTTP GET with the sun URL to get the title-listing of the latest system-titles, as .json. The deviceid in the URL is the same one in the above User-Agent section. HTTP header &amp;quot;Accept:application/json&amp;quot; is sent in the request.&lt;br /&gt;
&lt;br /&gt;
The response is json with a &amp;quot;system_update_metas&amp;quot; block, containing &amp;quot;title_id&amp;quot; and &amp;quot;title_version&amp;quot; entries. The actual server response only contains 1 title.&lt;br /&gt;
&lt;br /&gt;
Example, from 2.0 system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;{&amp;quot;timestamp&amp;quot;:REDACTED-TIMESTSAMP,&amp;quot;system_update_metas&amp;quot;:[{&amp;quot;title_id&amp;quot;:&amp;quot;0100000000000816&amp;quot;,&amp;quot;title_version&amp;quot;:201327002}]}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://sun.hac.%%.d4c.nintendo.net/v1/system_update_meta?device_id=%016llx&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== aqua ====&lt;br /&gt;
The following response is json from accessing the aqua URL:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;{&lt;br /&gt;
&amp;quot;contents_delivery_required_title_id&amp;quot;: &amp;quot;0100000000000816&amp;quot;,&lt;br /&gt;
&amp;quot;contents_delivery_required_title_version&amp;quot;: 0&lt;br /&gt;
}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A while after [[3.0.0]] release, the above title-version was changed to the one for v3.0(&amp;quot;Last-Modified: Thu, 29 Jun 2017 00:00:04 GMT&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://aqua.hac.%%.d4c.nintendo.net/required_system_update_meta?device_id=%016llx&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== atum/atumn ====&lt;br /&gt;
CDN for system-titles.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;atumn&amp;quot; is for system-titles and &amp;quot;atum&amp;quot; is for eShop titles.&lt;br /&gt;
&lt;br /&gt;
&#039;a&#039; is used when an input u8 is not 0x3, otherwise &#039;s&#039; is used. A seperate function using the &amp;quot;.../c/&amp;quot; URL is hard-coded to use &#039;c&#039;. This appears to match &#039;s&#039; usage attempts: the only URL that returned actual data with &#039;s&#039; was with titleID 0100000000000816.&lt;br /&gt;
&lt;br /&gt;
As of June 30, 2017, accessing old content via the atumn &amp;quot;/c/&amp;quot; and &amp;quot;/t/&amp;quot; URLs works fine.&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://%s.hac.%%.d4c.nintendo.net/t/%c/%016llx/%u?device_id=%016llx&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 Returns content like the below URL. First %s is atumn or atum. This is the content for [[NCA]]-type0. See below for %c. %016llx is titleID, %u is title-version.&lt;br /&gt;
 &lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://%s.hac.%%.d4c.nintendo.net/c/%c/%s&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 Used for downloading content. First %s is atumn or atum. %c is one of: &#039;c&#039;, &#039;a&#039;, or &#039;s&#039;. %s is just the hex-string NcaId. The server also returns two HTTP headers: &amp;quot;X-Nintendo-Content-Hash: {entire lowercase hex-string of the content SHA256 hash}&amp;quot; and &amp;quot;X-Nintendo-Content-ID: {lowercase hex-string for NcaId}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== superfly ====&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://superfly.hac.%%.d4c.nintendo.net/v1/t/%016llx/dv&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 %016llx is titleID, only for eShop titles it appears. Returns .json title-info.&lt;br /&gt;
 &lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://superfly.hac.%%.d4c.nintendo.net/v1/a/%016llx/dv&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 %016llx is titleID, only for eShop titles it appears. Output is similar to above URL.&lt;br /&gt;
&lt;br /&gt;
==== tagaya ====&lt;br /&gt;
VersionList for eShop titles.&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://tagaya.hac.%.eshop.nintendo.net/tagaya/hac_versionlist&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== beach ====&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://beach.hac.%.eshop.nintendo.net/v1/rom_cards?application_id=%016llx&amp;amp;rom_card_cert=%s&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://beach.hac.%.eshop.nintendo.net/v1/rom_cards/register?application_id=%016llx&amp;amp;rom_card_cert=%s&amp;amp;expected_gold_point=%d&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://beach.hac.%.eshop.nintendo.net/v1/my/devices/hac/link?lang=en&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://beach.hac.%.eshop.nintendo.net/v1/my/virtual_account?lang=en&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== pearljam ====&lt;br /&gt;
URLs:&lt;br /&gt;
 [5.0.0+] &amp;quot;&amp;lt;nowiki&amp;gt;https://pearljam.hac.%.eshop.nintendo.net/sugar&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 [5.0.0+] &amp;quot;&amp;lt;nowiki&amp;gt;https://pearljam.hac.%.eshop.nintendo.net/civil&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== tigers ====&lt;br /&gt;
Used for fetching common tickets for title updates.&lt;br /&gt;
&lt;br /&gt;
==== veer ====&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://veer.hac.%%.d4c.nintendo.net/v3/policy.json?context=%s&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Shop API ==&lt;br /&gt;
Domains for interacting with the online shop API.&lt;br /&gt;
&lt;br /&gt;
=== Servers ===&lt;br /&gt;
* &amp;quot;[[#ecs|ecs-%.hac.shop.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;[[#ias|ias-%.hac.shop.nintendo.net]]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== ecs ====&lt;br /&gt;
These URL strings were removed from nim with [15.0.0+].&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://ecs-%.hac.shop.nintendo.net/ecs/services/rest/AccountGetETickets&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://ecs-%.hac.shop.nintendo.net/ecs/services/rest/GetAccountStatus&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== ias ====&lt;br /&gt;
These URL strings were removed from nim with [15.0.0+].&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://ias-%.hac.shop.nintendo.net/ias/services/rest/Register&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://ias-%.hac.shop.nintendo.net/ias/services/rest/GetChallenge&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://ias-%.hac.shop.nintendo.net/ias/services/rest/Unregister&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://ias-%.hac.shop.nintendo.net/ias/services/rest/GetRegistrationInfo&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://ias-%.hac.shop.nintendo.net/ias/services/rest/CompleteETicketSync&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://ias-%.hac.shop.nintendo.net/ias/services/rest/AccountTransfer&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://ias-%.hac.shop.nintendo.net/ias/services/rest/SyncRegistration&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Services ==&lt;br /&gt;
The URLs for general online service servers on the Switch usually follow one of these formats:&lt;br /&gt;
 {server_name}.{environment}.{service_name}.srv.nintendo.net&lt;br /&gt;
 {server_name}-{environment}.{service_name}.srv.nintendo.net&lt;br /&gt;
&lt;br /&gt;
Where:&lt;br /&gt;
 {server_name}: One of the registered server names.&lt;br /&gt;
 {environment}: &amp;quot;lp1&amp;quot; (production), &amp;quot;dd1&amp;quot; (development) or &amp;quot;sp1&amp;quot; (production lottest staging).&lt;br /&gt;
 {service_name}: One of the various service names.&lt;br /&gt;
&lt;br /&gt;
=== Servers ===&lt;br /&gt;
* &amp;quot;[[#aauth|aauth-%.ndas.srv.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;[[#dauth|dauth-%.ndas.srv.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;[[#znc|api-%.znc.srv.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;api-%.pctl.srv.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;api-%.frs.srv.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;app-a04.%.npns.srv.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;app-b01.%.npns.srv.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;broker.%.npns.srv.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;consumer.%.npns.srv.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;[[BCAT_services#Data_reporting|receive-%.dg.srv.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;[[Error_Upload_services|receive-%.er.srv.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;nncs1-%.n.n.srv.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;nncs2-%.n.n.srv.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;g&amp;lt;game_server_id&amp;gt;-%.s.n.srv.nintendo.net&amp;quot;&lt;br /&gt;
* [4.0.0+] &amp;quot;[[#migration|migration.%.scsi.srv.nintendo.net]]&amp;quot;&lt;br /&gt;
* [6.0.0+] &amp;quot;[[#storage|storage.%.scsi.srv.nintendo.net]]&amp;quot;&lt;br /&gt;
* [9.0.0+] &amp;quot;[[#storage|storage.%.sata.srv.nintendo.net]]&amp;quot;&lt;br /&gt;
* [9.0.0+] &amp;quot;[[#permission|permission.%.sata.srv.nintendo.net]]&amp;quot;&lt;br /&gt;
* [20.0.0+] &amp;quot;pegasus.hac.%.pegasus.srv.nintendo.net&amp;quot;&lt;br /&gt;
* [20.0.0+] &amp;quot;transfer.hac.%.banco.srv.nintendo.net&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== aauth ====&lt;br /&gt;
Application authentication.&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://aauth-%.ndas.srv.nintendo.net/v1/application_auth_token&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://aauth-%.ndas.srv.nintendo.net/v1/time&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 [5.0.0+] &amp;quot;&amp;lt;nowiki&amp;gt;https://aauth-%.ndas.srv.nintendo.net/v2-44cd4221f90742b5f37a4948b37dacf024d0bb14dde86db0af20ec300a36a0fe/application_auth_token&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 Replaces previous application_auth_token URL.&lt;br /&gt;
&lt;br /&gt;
==== dauth ====&lt;br /&gt;
Device authentication.&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://dauth-%.ndas.srv.nintendo.net/v1/device_auth_token&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 CURLOPT_POSTFIELDS is set to the output from: snprintf(..., &amp;quot;system_version=%08x&amp;amp;client_id=%s&amp;quot;, &amp;lt;byte-swapped first 3 bytes from [[System_Version_Title]] loaded via [[Settings_services|settings]] cmd&amp;gt;, &amp;quot;&amp;lt;hard-coded hex string&amp;gt;&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 [4.0.0+] &amp;quot;&amp;lt;nowiki&amp;gt;https://dauth-%.ndas.srv.nintendo.net/439528b578b74475d24ec19264097f17d2cc578c8584816b644e7b7fa93044d7/device_auth_token&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 Replaces previous device_auth_token URL. &lt;br /&gt;
 &lt;br /&gt;
 [5.0.0+] &amp;quot;&amp;lt;nowiki&amp;gt;https://dauth-%.ndas.srv.nintendo.net/v3-59ed5fa1c25bb2aea8c4d73d74b919a94d89ed48d6865b728f63547943b17404/device_auth_token&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 Replaces previous device_auth_token URL.&lt;br /&gt;
 &lt;br /&gt;
 [5.0.0+] &amp;quot;&amp;lt;nowiki&amp;gt;https://dauth-%.ndas.srv.nintendo.net/v3-59ed5fa1c25bb2aea8c4d73d74b919a94d89ed48d6865b728f63547943b17404/challenge&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
 CURLOPT_POSTFIELDS is set to the output from: snprintf(..., &amp;quot;key_generation=%u&amp;quot;, 5);&lt;br /&gt;
&lt;br /&gt;
==== znc ====&lt;br /&gt;
Used by the Switch Online app to get app data, like the list of game-specific services to display.&lt;br /&gt;
&lt;br /&gt;
==== app ====&lt;br /&gt;
app-a04* uses XMPP with TLS over port 443, without HTTP. Sample request:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;stream:stream to=&amp;quot;app-a04.lp1.npns.srv.nintendo.net&amp;quot; xml:lang=&amp;quot;en&amp;quot; version=&amp;quot;1.0&amp;quot; xmlns=&amp;quot;jabber:client&amp;quot; xmlns:stream=&amp;quot;http://etherx.jabber.org/streams&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== migration ====&lt;br /&gt;
[[Migration_services|Migration]] service storage.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The below save_data_migrations URLs were moved elsewhere under [[#transfer|transfer]].&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
   &amp;lt;nowiki&amp;gt;https://migration.%.scsi.srv.nintendo.net/api/nx/v1/account_migrations/gen_key&lt;br /&gt;
  https://migration.%.scsi.srv.nintendo.net/api/nx/v1/account_migrations/get_key&lt;br /&gt;
  https://migration.%.scsi.srv.nintendo.net/api/nx/v1/save_data_migrations/gen_key&lt;br /&gt;
  https://migration.%.scsi.srv.nintendo.net/api/nx/v1/save_data_migrations/get_key&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== storage ====&lt;br /&gt;
[[OLSC_services|OLSC]] service (.scsi) and repair service (.sata) storage.&lt;br /&gt;
&lt;br /&gt;
==== permission ====&lt;br /&gt;
[[OLSC_services|OLSC]] repair service survey request.&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;https://permission.%.sata.srv.nintendo.net/api/nx/v1/customer_operations&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;https://permission.%.sata.srv.nintendo.net/api/nx/v1/customer_operations?survey_request_id=%llu&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  Request headers:&lt;br /&gt;
  &amp;gt; User-Agent: libcurl (nnHttp; 789f928b-138e-4b2f-afeb-1acae821d897; SDK {x.x.x.x sdkver}; Add-on {x.x.x.x sdkver})&lt;br /&gt;
  &amp;gt; Accept: */*&lt;br /&gt;
  &amp;gt; X-Device-Token: {device-token from dauth for SATA}&lt;br /&gt;
  &amp;gt; Content-Type: application/json&lt;br /&gt;
  &lt;br /&gt;
  Response (without survey_request_id): {&amp;quot;survey_requests&amp;quot;:[]}&lt;br /&gt;
&lt;br /&gt;
==== transfer ====&lt;br /&gt;
Used by [[Migration_services|Migration]] starting with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
The URL is &amp;quot;%s%s&amp;quot;, where the first &amp;quot;%s&amp;quot; is &amp;lt;nowiki&amp;gt;&amp;quot;https://transfer.hac.%.banco.srv.nintendo.net/api/console/v1/transfer_events&amp;quot;&amp;lt;/nowiki&amp;gt;, and the second &amp;quot;%s&amp;quot; is one of the following:&lt;br /&gt;
&lt;br /&gt;
  /start&lt;br /&gt;
  /%lld/%s (where %s is one of the following as selected by an input param: &amp;quot;finish_transfer&amp;quot;, &amp;quot;finish_upload&amp;quot;, &amp;quot;finish_download&amp;quot;, &amp;quot;abort_transfer&amp;quot;, &amp;quot;abort_upload&amp;quot;)&lt;br /&gt;
  /%lld&lt;br /&gt;
  /%lld/rollback&lt;br /&gt;
  /%lld/register_destination&lt;br /&gt;
  ?type=%d&lt;br /&gt;
  &amp;quot;/%lld/save_datas/%lld/generate_key_seed_package&amp;quot; / &amp;quot;/%lld/generate_key_seed_package&amp;quot;, depending on an input param (the former is only used by [[Migration_services|IDownloader]] cmd400)&lt;br /&gt;
  /%lld/save_datas/start_upload&lt;br /&gt;
  /%lld/save_datas/%lld/finish_upload&lt;br /&gt;
  /%lld/save_datas/%lld&lt;br /&gt;
  /%lld/save_datas/%lld/component_files/start_upload&lt;br /&gt;
  /%lld/save_datas/%lld/component_files/%lld/finish_upload&lt;br /&gt;
  /%lld/save_datas/%lld/component_files&lt;br /&gt;
  /%lld/save_datas&lt;br /&gt;
  /%lld/save_datas/%lld/start_download&lt;br /&gt;
  /%lld/save_datas/%lld/finish_download&lt;br /&gt;
  /%lld/save_datas/%lld/component_files&lt;br /&gt;
  /%lld/album_data_archives/start_upload&lt;br /&gt;
  /%lld/album_data_archives/%lld/finish_upload&lt;br /&gt;
  /%lld/album_data_archives/%lld&lt;br /&gt;
  /%lld/album_data_archives/%lld/start_download&lt;br /&gt;
  /%lld/album_data_archives/%lld&lt;br /&gt;
  /%lld/album_data_archives/%lld/finish_download&lt;br /&gt;
  /%lld/album_data_archives&lt;br /&gt;
&lt;br /&gt;
These use the following request headers:&lt;br /&gt;
  User-Agent: libcurl (nnHttp; {...})&lt;br /&gt;
  Accept: */*&lt;br /&gt;
  Content-Type: application/json&lt;br /&gt;
  Authorization: Bearer {token}&lt;br /&gt;
  {Content-Length as needed}&lt;br /&gt;
&lt;br /&gt;
The above token is from using [[Account_services|IManagerForSystemService EnsureIdTokenCacheAsync]], with the output from [[Account_services|IManagerForSystemService LoadIdTokenCache]] being used as the token.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/start&amp;quot;:&lt;br /&gt;
** The json POST data contains the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;type&amp;quot;:&amp;lt;type&amp;gt;,&amp;quot;scope&amp;quot;:&amp;lt;scope&amp;gt;,&amp;quot;src_device_appearance_main&amp;quot;:&amp;quot;&amp;lt;str0&amp;gt;&amp;quot;,&amp;quot;src_device_appearance_controller&amp;quot;:&amp;quot;&amp;lt;str1&amp;gt;&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;type&amp;gt; is 0 for local (nn::migration::device::IServer and nn::migration::savedata::IServer), 1 for Uploader (nn::migration::device::IUploader).&lt;br /&gt;
*** &amp;lt;scope&amp;gt; is 0 for device (nn::migration::device::IServer and nn::migration::device::IUploader), 1 for savedata (nn::migration::savedata::IServer).&lt;br /&gt;
*** &amp;lt;str0&amp;gt; is the output from [[NS_services|ns]] IApplicationManagerInterface cmd4063, &amp;lt;str1&amp;gt; is from cmd4064.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 201):&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;transfer_event&amp;quot;:{&amp;quot;transfer_event_id&amp;quot;:&amp;lt;number&amp;gt;,&amp;quot;status&amp;quot;:&amp;lt;status_str&amp;gt;,&amp;quot;error&amp;quot;:&amp;lt;str&amp;gt;,&amp;quot;src_device_serial&amp;quot;:&amp;lt;str&amp;gt;,&amp;quot;src_device_appearance_main&amp;quot;:&amp;lt;str&amp;gt;,&amp;quot;dst_device_serial&amp;quot;:&amp;lt;str&amp;gt;,&amp;quot;src_device_type&amp;quot;:&amp;lt;unknown&amp;gt;,&amp;quot;created_at&amp;quot;:&amp;lt;timestamp&amp;gt;,&amp;quot;expires_at&amp;quot;:&amp;lt;timestamp&amp;gt;}}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** The minimum required fields are status and created_at. &amp;lt;status_str&amp;gt; must match one of various strings, such as &amp;quot;started&amp;quot;.&lt;br /&gt;
*** The output transfer_event_id is then used as the first &amp;quot;%lld&amp;quot; in the above URIs.&lt;br /&gt;
&lt;br /&gt;
== Others ==&lt;br /&gt;
Miscellaneous domains for various APIs and tests.&lt;br /&gt;
&lt;br /&gt;
=== Servers ===&lt;br /&gt;
Account metadata:&lt;br /&gt;
* &amp;quot;e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com&amp;quot;&lt;br /&gt;
* &amp;quot;accounts.nintendo.com&amp;quot;&lt;br /&gt;
* &amp;quot;api.accounts.nintendo.com&amp;quot;&lt;br /&gt;
* &amp;quot;c-%.accounts.nintendo.com&amp;quot;&lt;br /&gt;
* &amp;quot;capi.%.op2.nintendo.net&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[[NIM_services|nim]]:&lt;br /&gt;
* &amp;quot;bvc-hac-%.cdn.nintendo.net&amp;quot;&lt;br /&gt;
&lt;br /&gt;
News, friends and game content:&lt;br /&gt;
* &amp;quot;bcat-topics-%.cdn.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;bcat-list-%.cdn.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;bcat-data-%.cdn.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;bcat-web-%.cdn.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;app.%.five.nintendo.net&amp;quot;&lt;br /&gt;
* [6.0.0+] &amp;quot;scsi-policy-%.cdn.nintendo.net&amp;quot;&lt;br /&gt;
&lt;br /&gt;
NSO webapplet [11.0.0+]:&lt;br /&gt;
* &amp;quot;%.nso.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;atum-img-%.cdn.nintendo.net&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Connection:&lt;br /&gt;
* &amp;quot;ctest.cdn.nintendo.net&amp;quot; (replaces &amp;quot;conntest.nintendowifi.net&amp;quot;)&lt;br /&gt;
* &amp;quot;nasc.nintendowifi.net&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Error and status:&lt;br /&gt;
* &amp;quot;[[#service-status|service-status-%.cdn.nintendo.net]]&amp;quot;&lt;br /&gt;
* &amp;quot;problems.dragons.nintendo.net&amp;quot;&lt;br /&gt;
* &amp;quot;moon.nintendo.com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== bvc ====&lt;br /&gt;
Used by nim [[NIM_services#RequestCheckSafeSystemVersion|RequestCheckSafeSystemVersion]].&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;&amp;quot;https://bvc-hac-%.cdn.nintendo.net/%d-%d-%d&amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The data for each &amp;quot;%d&amp;quot; is the first 3-bytes from the [[System_Version_Title|SystemVersion]].&lt;br /&gt;
&lt;br /&gt;
==== scsi-policy ====&lt;br /&gt;
Used by [[OLSC_services|OLSC]] and [[Migration_services|migration]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This is no longer used by [[Migration_services|migration]].&lt;br /&gt;
&lt;br /&gt;
Migration URL:&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;&amp;quot;https://scsi-policy-%.cdn.nintendo.net/api/nx/v1/save_data_migration_policy/%016llx/%05u?dtoken=&amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* save_data_migration_policy: &amp;quot;%016llx&amp;quot; is the [[NCM_services#ApplicationId|ApplicationId]], &amp;quot;%05u&amp;quot; is version&amp;gt;&amp;gt;16 from [[NS_services#IApplicationVersionInterface|ns GetLaunchRequiredVersion]]. The value of dtoken is the dauth edge token for scsi. The request headers are: &amp;quot;User-Agent: libcurl (nnHttp;...&amp;quot; and &amp;quot;Accept: */*&amp;quot;.&lt;br /&gt;
** The response json is &amp;lt;code&amp;gt;{&amp;quot;save_data_migration&amp;quot;: &amp;lt;str&amp;gt;}&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;&amp;lt;str&amp;gt;&amp;lt;/code&amp;gt; is &amp;quot;OK&amp;quot; or &amp;quot;NG&amp;quot; (other values trigger error).&lt;br /&gt;
&lt;br /&gt;
==== service-status ====&lt;br /&gt;
[[Error_applet|Error applet]] status.&lt;br /&gt;
&lt;br /&gt;
URLs:&lt;br /&gt;
 &amp;quot;&amp;lt;nowiki&amp;gt;https://service-status-%.cdn.nintendo.net/service_status_hac.json&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= User-Agent =&lt;br /&gt;
[[NIM_services|NIM]] generates two User-Agent strings:&lt;br /&gt;
 snprintf(..., &amp;quot;User-Agent: NintendoSDK Firmware/%s-%u (platform:%s; did:%016llx; eid:%s)&amp;quot;, &amp;lt;string at [[System_Version_Title|sysver]]+0x68&amp;gt;, {u32 from [[System_Version_Title|sysver]]+4}, &amp;quot;NX&amp;quot;, DeviceId, {[[Sockets_services#GetEnvironmentIdentifier|GetEnvironmentIdentifier]] output});&lt;br /&gt;
  &lt;br /&gt;
 snprintf(..., &amp;quot;User-Agent: NintendoSDK Firmware/%s-%u (platform:%s; eid:%s)&amp;quot;, &amp;lt;string at [[System_Version_Title|sysver]]+0x68&amp;gt;, {u32 from [[System_Version_Title|sysver]]+4}, &amp;quot;NX&amp;quot;, DeviceId, {[[Sockets_services#GetEnvironmentIdentifier|GetEnvironmentIdentifier]] output});&lt;br /&gt;
&lt;br /&gt;
Where the 64bit DeviceId is parsed from the 0x10-bytes at outbuf+0xC6 from [[Settings_services|set:cal]] GetEciDeviceCertificate (DeviceCert_certname+2, aka where the hex string for the DeviceId is).&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14673</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14673"/>
		<updated>2026-05-04T21:51:07Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* RequestServerProfile */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || Uuid (from &amp;lt;code&amp;gt;nn::util::GenerateUuid()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || ApplicationIdsCount (arraycount from [[#Cmd1110]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x8 || [[Network|transfer_event_id]] from the [[#PrepareAsync|/start]] request, then used with the remaining network requests.&lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x134 || 0x10 || Zeros with savedata.&lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The Uuid must be non-zero.&lt;br /&gt;
* The ApplicationIdsCount must be 0x1-0x800.&lt;br /&gt;
* The ApplicationId must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14668</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14668"/>
		<updated>2026-05-04T03:51:28Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* RequestServerProfile */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || Uuid (from &amp;lt;code&amp;gt;nn::util::GenerateUuid()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || ApplicationIdsCount (arraycount from [[#Cmd1110]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x134 || 0x10 || Zeros with savedata.&lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The Uuid must be non-zero.&lt;br /&gt;
* The ApplicationIdsCount must be 0x1-0x800.&lt;br /&gt;
* The ApplicationId must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14664</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14664"/>
		<updated>2026-05-04T00:41:09Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* RequestServerProfile */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || Uuid (from &amp;lt;code&amp;gt;nn::util::GenerateUuid()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || ApplicationIdsCount (arraycount from [[#Cmd1110]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x134 || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The Uuid must be non-zero.&lt;br /&gt;
* The ApplicationIdsCount must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14663</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14663"/>
		<updated>2026-05-03T23:02:48Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Value 0x1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || Uuid (from &amp;lt;code&amp;gt;nn::util::GenerateUuid()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || ApplicationIdsCount (arraycount from [[#Cmd1110]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x14 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The Uuid must be non-zero.&lt;br /&gt;
* The ApplicationIdsCount must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14662</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14662"/>
		<updated>2026-05-03T19:15:57Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* mig:usr */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14661</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14661"/>
		<updated>2026-05-03T18:57:28Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], an [[NCM_services#ApplicationId|ApplicationId]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 [[#Cmd1110|tmem_size]], a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the input array is passed directly instead of from a single input [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== ListApplicationIds ===&lt;br /&gt;
Takes a s32 offset, a type-0x6 output buffer containing an array of [[NCM_services#ApplicationId|ApplicationIds]], returns a s32 total_out.&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output [[NCM_services#ApplicationId|ApplicationId]].&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output (equivalent to [[#ListApplicationIds|ListApplicationIds]] with the state field as the offset).&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] [[#ListApplicationIds|ListApplicationIds]]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14660</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14660"/>
		<updated>2026-05-03T05:07:01Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32 tmem_size, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes an u32 tmem_size, an [[Account_services|Uid]], a type-0x19 input buffer containing a [[#ServerProfile|ServerProfile]], a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
The tmem_size must be at least 0x504BB0.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14659</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14659"/>
		<updated>2026-05-02T17:50:31Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Handles state cleanup if needed.&lt;br /&gt;
* Calls a func. This uses various [[OLSC_services|olsc:s]] functionality.&lt;br /&gt;
* Sets the state flag which was used for the above cleanup.&lt;br /&gt;
* Calls a func which uses [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId. The output is unused.&lt;br /&gt;
* Calls a vfunc, returns 0 if ret is true.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Handles [[Sockets_services|sockets]]/etc initialization, enters a nifm block.&lt;br /&gt;
* Uses network request [[Network|transfer_events/start]]. The output from this func is copied into state.&lt;br /&gt;
* Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls the same olsc func as [[#PrepareAsync|PrepareAsync]].&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14657</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14657"/>
		<updated>2026-05-02T05:06:33Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Calls a func to get a state field, if this is -1 this then just returns 0.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Handles [[Sockets_services|sockets]]/etc initialization.&lt;br /&gt;
*** Enters a block which uses nifm.&lt;br /&gt;
*** Uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
*** Nifm usage ends here. Handles [[Sockets_services|sockets]] cleanup, etc.&lt;br /&gt;
** If the above func returned an error, depending on the Result this may call a func which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14656</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14656"/>
		<updated>2026-05-02T04:02:35Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] [[#AbortAsync2|AbortAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Runs essentially the same code-block as [[#CompleteAsync|CompleteAsync]] for the connected flag, without the network messages.&lt;br /&gt;
* When a vfunc returns true, call a func.&lt;br /&gt;
* Calls vfuncs then returns.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input bool, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This is roughly the same as [[#AbortAsync|AbortAsync]] except for the additional functionality done by the async task (etc), for when the input bool is set.&lt;br /&gt;
&lt;br /&gt;
The async task does the following in that block when the input bool is set (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* This block also only runs when a vfunc ret is false.&lt;br /&gt;
** {...}&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort_2|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync_2|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort_2|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14655</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14655"/>
		<updated>2026-05-02T02:58:05Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* IServer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls the same two funcs as [[#DebugWaitStateSynchronizationFinalizedAsync|DebugWaitStateSynchronizationFinalizedAsync]].&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
=== DebugWaitStateSynchronizationFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
* Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14654</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14654"/>
		<updated>2026-05-02T02:26:32Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* When the [[#WaitConnectionAsync|connected]] state flag is set:&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]], then sends the response.&lt;br /&gt;
** Calls a func. This is basically identical to the above func, except a field written to stack is value 5 instead of 4.&lt;br /&gt;
** Handles closing the socket (similar to elsewhere).&lt;br /&gt;
** Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
** Clears the connected state flag.&lt;br /&gt;
* Calls a vfunc, throwing an error when ret is false.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls vfuncs, then returns.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync_2|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync_2|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14653</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14653"/>
		<updated>2026-05-01T20:19:44Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* TransferNext */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Error_codes&amp;diff=14652</id>
		<title>Error codes</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Error_codes&amp;diff=14652"/>
		<updated>2026-05-01T18:03:52Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* Error Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Structure =&lt;br /&gt;
These have been redesigned from the 3DS so that they fit within a Aarch64 MOV instruction immediate most of the time (without requiring the additional MOVK).&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bits || Field&lt;br /&gt;
|-&lt;br /&gt;
| 0-8 || Module&lt;br /&gt;
|-&lt;br /&gt;
| 9-21 || Description&lt;br /&gt;
|-&lt;br /&gt;
| 22-31 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When a fatal error is received the error code is outputted using the following formatter:&lt;br /&gt;
  %04d-%04d&lt;br /&gt;
&lt;br /&gt;
Where the first code is &amp;lt;code&amp;gt;2000 + Module&amp;lt;/code&amp;gt;, and the second being &amp;lt;code&amp;gt;Description&amp;lt;/code&amp;gt;. Bits &amp;gt;=22 from the error code are reserved and unused.&lt;br /&gt;
&lt;br /&gt;
= Result Errors =&lt;br /&gt;
General errors used by system modules and applications.&lt;br /&gt;
&lt;br /&gt;
== Modules ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Svc&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Fs&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Os&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Htcs&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Ncm&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Dd&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Osdbg&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Lr&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Ldr&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Sf&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Sf_Hipc&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Tma&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Dmnt&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Gds&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Pm&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Ns&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Bsdsockets&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Htc&lt;br /&gt;
|-&lt;br /&gt;
| 19 || Tsc&lt;br /&gt;
|-&lt;br /&gt;
| 20 || Kvdb&lt;br /&gt;
|-&lt;br /&gt;
| 21 || Sm&lt;br /&gt;
|-&lt;br /&gt;
| 22 || Ro&lt;br /&gt;
|-&lt;br /&gt;
| 23 || Gc&lt;br /&gt;
|-&lt;br /&gt;
| 24 || Sdmmc&lt;br /&gt;
|-&lt;br /&gt;
| 25 || Ovln&lt;br /&gt;
|-&lt;br /&gt;
| 26 || Spl&lt;br /&gt;
|-&lt;br /&gt;
| 27 || Socket&lt;br /&gt;
|-&lt;br /&gt;
| 28 || Dt&lt;br /&gt;
|-&lt;br /&gt;
| 29 || Htclow&lt;br /&gt;
|-&lt;br /&gt;
| 30 || Ddsf&lt;br /&gt;
|-&lt;br /&gt;
| 31 || Htcfs&lt;br /&gt;
|-&lt;br /&gt;
| 32 || Async&lt;br /&gt;
|-&lt;br /&gt;
| 33 || Util&lt;br /&gt;
|-&lt;br /&gt;
| 34 || &lt;br /&gt;
|-&lt;br /&gt;
| 35 || Tipc&lt;br /&gt;
|-&lt;br /&gt;
| 36 || &lt;br /&gt;
|-&lt;br /&gt;
| 37 || Anif&lt;br /&gt;
|-&lt;br /&gt;
| 38 || &lt;br /&gt;
|-&lt;br /&gt;
| 39 || Crt&lt;br /&gt;
|-&lt;br /&gt;
| 100 || Eth&lt;br /&gt;
|-&lt;br /&gt;
| 101 || I2c&lt;br /&gt;
|-&lt;br /&gt;
| 102 || Gpio&lt;br /&gt;
|-&lt;br /&gt;
| 103 || Uart&lt;br /&gt;
|-&lt;br /&gt;
| 104 || Cpad&lt;br /&gt;
|-&lt;br /&gt;
| 105 || Settings&lt;br /&gt;
|-&lt;br /&gt;
| 106 || Ftm&lt;br /&gt;
|-&lt;br /&gt;
| 107 || Wlan&lt;br /&gt;
|-&lt;br /&gt;
| 108 || Xcd&lt;br /&gt;
|-&lt;br /&gt;
| 109 || Tmp451&lt;br /&gt;
|-&lt;br /&gt;
| 110 || Nifm&lt;br /&gt;
|-&lt;br /&gt;
| 111 || Codec&lt;br /&gt;
|-&lt;br /&gt;
| 112 || Lsm6ds3&lt;br /&gt;
|-&lt;br /&gt;
| 113 || Bluetooth&lt;br /&gt;
|-&lt;br /&gt;
| 114 || Vi&lt;br /&gt;
|-&lt;br /&gt;
| 115 || Nfp&lt;br /&gt;
|-&lt;br /&gt;
| 116 || Time&lt;br /&gt;
|-&lt;br /&gt;
| 117 || Fgm&lt;br /&gt;
|-&lt;br /&gt;
| 118 || Oe&lt;br /&gt;
|-&lt;br /&gt;
| 119 || Bh1730fvc&lt;br /&gt;
|-&lt;br /&gt;
| 120 || Pcie&lt;br /&gt;
|-&lt;br /&gt;
| 121 || Friends&lt;br /&gt;
|-&lt;br /&gt;
| 122 || Bcat&lt;br /&gt;
|-&lt;br /&gt;
| 123 || Ssl&lt;br /&gt;
|-&lt;br /&gt;
| 124 || Account&lt;br /&gt;
|-&lt;br /&gt;
| 125 || News&lt;br /&gt;
|-&lt;br /&gt;
| 126 || Mii&lt;br /&gt;
|-&lt;br /&gt;
| 127 || Nfc&lt;br /&gt;
|-&lt;br /&gt;
| 128 || Am&lt;br /&gt;
|-&lt;br /&gt;
| 129 || Prepo&lt;br /&gt;
|-&lt;br /&gt;
| 130 || Ahid&lt;br /&gt;
|-&lt;br /&gt;
| 131 || Applet&lt;br /&gt;
|-&lt;br /&gt;
| 132 || Ae&lt;br /&gt;
|-&lt;br /&gt;
| 133 || Pcv&lt;br /&gt;
|-&lt;br /&gt;
| 134 || Usb_Pd&lt;br /&gt;
|-&lt;br /&gt;
| 135 || Bpc&lt;br /&gt;
|-&lt;br /&gt;
| 136 || Psm&lt;br /&gt;
|-&lt;br /&gt;
| 137 || Nim&lt;br /&gt;
|-&lt;br /&gt;
| 138 || Psc&lt;br /&gt;
|-&lt;br /&gt;
| 139 || Tc&lt;br /&gt;
|-&lt;br /&gt;
| 140 || Usb&lt;br /&gt;
|-&lt;br /&gt;
| 141 || Nsd&lt;br /&gt;
|-&lt;br /&gt;
| 142 || Pctl&lt;br /&gt;
|-&lt;br /&gt;
| 143 || Btm&lt;br /&gt;
|-&lt;br /&gt;
| 144 || La&lt;br /&gt;
|-&lt;br /&gt;
| 145 || Es&lt;br /&gt;
|-&lt;br /&gt;
| 146 || Ngc&lt;br /&gt;
|-&lt;br /&gt;
| 147 || Erpt&lt;br /&gt;
|-&lt;br /&gt;
| 148 || Apm&lt;br /&gt;
|-&lt;br /&gt;
| 149 || Cec&lt;br /&gt;
|-&lt;br /&gt;
| 150 || Profiler&lt;br /&gt;
|-&lt;br /&gt;
| 151 || Eupld&lt;br /&gt;
|-&lt;br /&gt;
| 152 || Lidbe&lt;br /&gt;
|-&lt;br /&gt;
| 153 || Audio&lt;br /&gt;
|-&lt;br /&gt;
| 154 || Npns&lt;br /&gt;
|-&lt;br /&gt;
| 155 || Http&lt;br /&gt;
|-&lt;br /&gt;
| 156 || Idle&lt;br /&gt;
|-&lt;br /&gt;
| 157 || Arp&lt;br /&gt;
|-&lt;br /&gt;
| 158 || Updater&lt;br /&gt;
|-&lt;br /&gt;
| 159 || Swkbd&lt;br /&gt;
|-&lt;br /&gt;
| 160 || Netdiag&lt;br /&gt;
|-&lt;br /&gt;
| 161 || Nfc_Mifare&lt;br /&gt;
|-&lt;br /&gt;
| 162 || Err&lt;br /&gt;
|-&lt;br /&gt;
| 163 || Fatal&lt;br /&gt;
|-&lt;br /&gt;
| 164 || Ec&lt;br /&gt;
|-&lt;br /&gt;
| 165 || Spsm&lt;br /&gt;
|-&lt;br /&gt;
| 166 || Aoc&lt;br /&gt;
|-&lt;br /&gt;
| 167 || Bgtc&lt;br /&gt;
|-&lt;br /&gt;
| 168 || Creport&lt;br /&gt;
|-&lt;br /&gt;
| 169 || Sasbus&lt;br /&gt;
|-&lt;br /&gt;
| 170 || Pl&lt;br /&gt;
|-&lt;br /&gt;
| 171 || Cdmsc&lt;br /&gt;
|-&lt;br /&gt;
| 172 || Audioctrl&lt;br /&gt;
|-&lt;br /&gt;
| 173 || Lbl&lt;br /&gt;
|-&lt;br /&gt;
| 174 || &lt;br /&gt;
|-&lt;br /&gt;
| 175 || Jit&lt;br /&gt;
|-&lt;br /&gt;
| 176 || Hdcp&lt;br /&gt;
|-&lt;br /&gt;
| 177 || Omm&lt;br /&gt;
|-&lt;br /&gt;
| 178 || Pdm&lt;br /&gt;
|-&lt;br /&gt;
| 179 || Olsc&lt;br /&gt;
|-&lt;br /&gt;
| 180 || Srepo&lt;br /&gt;
|-&lt;br /&gt;
| 181 || Dauth&lt;br /&gt;
|-&lt;br /&gt;
| 182 || Stdfu&lt;br /&gt;
|-&lt;br /&gt;
| 183 || Dbg&lt;br /&gt;
|-&lt;br /&gt;
| 184 || Cdacm&lt;br /&gt;
|-&lt;br /&gt;
| 185 || Tcap&lt;br /&gt;
|-&lt;br /&gt;
| 186 || Dhcps&lt;br /&gt;
|-&lt;br /&gt;
| 187 || Spi&lt;br /&gt;
|-&lt;br /&gt;
| 188 || Avm&lt;br /&gt;
|-&lt;br /&gt;
| 189 || Pwm&lt;br /&gt;
|-&lt;br /&gt;
| 190 || Dnsserver&lt;br /&gt;
|-&lt;br /&gt;
| 191 || Rtc&lt;br /&gt;
|-&lt;br /&gt;
| 192 || Regulator&lt;br /&gt;
|-&lt;br /&gt;
| 193 || Led&lt;br /&gt;
|-&lt;br /&gt;
| 194 || HtcTool&lt;br /&gt;
|-&lt;br /&gt;
| 195 || Sio&lt;br /&gt;
|-&lt;br /&gt;
| 196 || Pcm&lt;br /&gt;
|-&lt;br /&gt;
| 197 || Clkrst&lt;br /&gt;
|-&lt;br /&gt;
| 198 || Powctl&lt;br /&gt;
|-&lt;br /&gt;
| 199 || Hiddriver&lt;br /&gt;
|-&lt;br /&gt;
| 200 || Dma&lt;br /&gt;
|-&lt;br /&gt;
| 201 || Audio_Old&lt;br /&gt;
|-&lt;br /&gt;
| 202 || Hid&lt;br /&gt;
|-&lt;br /&gt;
| 203 || Ldn&lt;br /&gt;
|-&lt;br /&gt;
| 204 || Cs&lt;br /&gt;
|-&lt;br /&gt;
| 205 || Irsensor&lt;br /&gt;
|-&lt;br /&gt;
| 206 || Capsrv&lt;br /&gt;
|-&lt;br /&gt;
| 207 || Mm&lt;br /&gt;
|-&lt;br /&gt;
| 208 || Manu&lt;br /&gt;
|-&lt;br /&gt;
| 209 || Atk&lt;br /&gt;
|-&lt;br /&gt;
| 210 || Web&lt;br /&gt;
|-&lt;br /&gt;
| 211 || Lcs&lt;br /&gt;
|-&lt;br /&gt;
| 212 || Grc&lt;br /&gt;
|-&lt;br /&gt;
| 213 || Repair&lt;br /&gt;
|-&lt;br /&gt;
| 214 || Album&lt;br /&gt;
|-&lt;br /&gt;
| 215 || Rid&lt;br /&gt;
|-&lt;br /&gt;
| 216 || Migration&lt;br /&gt;
|-&lt;br /&gt;
| 217 || Migration_Idc&lt;br /&gt;
|-&lt;br /&gt;
| 218 || Hidbus&lt;br /&gt;
|-&lt;br /&gt;
| 219 || Ens&lt;br /&gt;
|-&lt;br /&gt;
| 220 || Nd&lt;br /&gt;
|-&lt;br /&gt;
| 221 || Ndd&lt;br /&gt;
|-&lt;br /&gt;
| 222 || Toycon&lt;br /&gt;
|-&lt;br /&gt;
| 223 || Websocket&lt;br /&gt;
|-&lt;br /&gt;
| 224 || Socketio&lt;br /&gt;
|-&lt;br /&gt;
| 225 || &lt;br /&gt;
|-&lt;br /&gt;
| 226 || &lt;br /&gt;
|-&lt;br /&gt;
| 227 || Dcdmtp&lt;br /&gt;
|-&lt;br /&gt;
| 228 || Pgl&lt;br /&gt;
|-&lt;br /&gt;
| 229 || Notification&lt;br /&gt;
|-&lt;br /&gt;
| 230 || Ins&lt;br /&gt;
|-&lt;br /&gt;
| 231 || Lp2p&lt;br /&gt;
|-&lt;br /&gt;
| 232 || Rcd&lt;br /&gt;
|-&lt;br /&gt;
| 233 || Icm40607&lt;br /&gt;
|-&lt;br /&gt;
| 234 || &lt;br /&gt;
|-&lt;br /&gt;
| 235 || Prc&lt;br /&gt;
|-&lt;br /&gt;
| 236 || &lt;br /&gt;
|-&lt;br /&gt;
| 237 || Bridgectrl&lt;br /&gt;
|-&lt;br /&gt;
| 238 || Err_Context&lt;br /&gt;
|-&lt;br /&gt;
| 239 || Mnpp&lt;br /&gt;
|-&lt;br /&gt;
| 240 || Hshl&lt;br /&gt;
|-&lt;br /&gt;
| 241 || Ringcon&lt;br /&gt;
|-&lt;br /&gt;
| 242 || Capmtp&lt;br /&gt;
|-&lt;br /&gt;
| 243 || [S2] NvDrv2?&lt;br /&gt;
|-&lt;br /&gt;
| 244 || Dp2hdmi&lt;br /&gt;
|-&lt;br /&gt;
| 245 || Cradle&lt;br /&gt;
|-&lt;br /&gt;
| 246 || Sprofile&lt;br /&gt;
|-&lt;br /&gt;
| 247 || &lt;br /&gt;
|-&lt;br /&gt;
| 248 || Icm42607p&lt;br /&gt;
|-&lt;br /&gt;
| 249 || [S2] Imf&lt;br /&gt;
|-&lt;br /&gt;
| 250 || Ndrm&lt;br /&gt;
|-&lt;br /&gt;
| 251 || Fst2&lt;br /&gt;
|-&lt;br /&gt;
| 252 || &lt;br /&gt;
|-&lt;br /&gt;
| 253 || Ts&lt;br /&gt;
|-&lt;br /&gt;
| 254 || &lt;br /&gt;
|-&lt;br /&gt;
| 255 || &lt;br /&gt;
|-&lt;br /&gt;
| 260 || Splay&lt;br /&gt;
|-&lt;br /&gt;
| 266 || &lt;br /&gt;
|-&lt;br /&gt;
| 287 || [S2]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 301 || &lt;br /&gt;
|-&lt;br /&gt;
| 302 || &lt;br /&gt;
|-&lt;br /&gt;
| 303 || &lt;br /&gt;
|-&lt;br /&gt;
| 304 || &lt;br /&gt;
|-&lt;br /&gt;
| 305 || &lt;br /&gt;
|-&lt;br /&gt;
| 306 || Nex&lt;br /&gt;
|-&lt;br /&gt;
| 307 || &lt;br /&gt;
|-&lt;br /&gt;
| 308 || &lt;br /&gt;
|-&lt;br /&gt;
| 309 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 311 || &lt;br /&gt;
|-&lt;br /&gt;
| 312 || &lt;br /&gt;
|-&lt;br /&gt;
| 313 || &lt;br /&gt;
|-&lt;br /&gt;
| 314 || &lt;br /&gt;
|-&lt;br /&gt;
| 315 || &lt;br /&gt;
|-&lt;br /&gt;
| 316 || &lt;br /&gt;
|-&lt;br /&gt;
| 317 || &lt;br /&gt;
|-&lt;br /&gt;
| 318 || &lt;br /&gt;
|-&lt;br /&gt;
| 319 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 321 || Npln&lt;br /&gt;
|-&lt;br /&gt;
| 452 || [S2]&lt;br /&gt;
|-&lt;br /&gt;
| 499 || Tspm&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Devmenu&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Error Codes ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Module || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
| 0xA01 || 1 || 5 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC01 || 1 || 6 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xE01 || 1 || 7 || OutOfSessions&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C01 || 1 || 14 || InvalidArgument&lt;br /&gt;
|-&lt;br /&gt;
| 0x4201 || 1 || 33 || NotImplemented&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C01 || 1 || 54 || StopProcessingException&lt;br /&gt;
|-&lt;br /&gt;
| 0x7201 || 1 || 57 || NoSynchronizationObject&lt;br /&gt;
|-&lt;br /&gt;
| 0x7601 || 1 || 59 || TerminationRequested&lt;br /&gt;
|-&lt;br /&gt;
| 0x8C01 || 1 || 70 || NoEvent&lt;br /&gt;
|-&lt;br /&gt;
| 0x9401 || 1 || 74 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xCA01 || 1 || 101 || InvalidSize&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC01 || 1 || 102 || InvalidAddress&lt;br /&gt;
|-&lt;br /&gt;
| 0xCE01 || 1 || 103 || OutOfResource&lt;br /&gt;
|-&lt;br /&gt;
| 0xD001 || 1 || 104 || OutOfMemory&lt;br /&gt;
|-&lt;br /&gt;
| 0xD201 || 1 || 105 || OutOfHandles&lt;br /&gt;
|-&lt;br /&gt;
| 0xD401 || 1 || 106 || InvalidCurrentMemory&lt;br /&gt;
|-&lt;br /&gt;
| 0xD801 || 1 || 108 || InvalidNewMemoryPermission&lt;br /&gt;
|-&lt;br /&gt;
| 0xDA01 || 1 || 109 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xDC01 || 1 || 110 || InvalidMemoryRegion&lt;br /&gt;
|-&lt;br /&gt;
| 0xE001 || 1 || 112 || InvalidPriority&lt;br /&gt;
|-&lt;br /&gt;
| 0xE201 || 1 || 113 || InvalidCoreId&lt;br /&gt;
|-&lt;br /&gt;
| 0xE401 || 1 || 114 || InvalidHandle&lt;br /&gt;
|-&lt;br /&gt;
| 0xE601 || 1 || 115 || InvalidPointer&lt;br /&gt;
|-&lt;br /&gt;
| 0xE801 || 1 || 116 || InvalidCombination&lt;br /&gt;
|-&lt;br /&gt;
| 0xEA01 || 1 || 117 || TimedOut&lt;br /&gt;
|-&lt;br /&gt;
| 0xEC01 || 1 || 118 || Cancelled&lt;br /&gt;
|-&lt;br /&gt;
| 0xEE01 || 1 || 119 || OutOfRange&lt;br /&gt;
|-&lt;br /&gt;
| 0xF001 || 1 || 120 || InvalidEnumValue&lt;br /&gt;
|-&lt;br /&gt;
| 0xF201 || 1 || 121 || NotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0xF401 || 1 || 122 || Busy&lt;br /&gt;
|-&lt;br /&gt;
| 0xF601 || 1 || 123 || SessionClosed&lt;br /&gt;
|-&lt;br /&gt;
| 0xF801 || 1 || 124 || NotHandled&lt;br /&gt;
|-&lt;br /&gt;
| 0xFA01 || 1 || 125 || InvalidState&lt;br /&gt;
|-&lt;br /&gt;
| 0xFC01 || 1 || 126 || ReservedUsed&lt;br /&gt;
|-&lt;br /&gt;
| 0xFE01 || 1 || 127 || NotSupported&lt;br /&gt;
|-&lt;br /&gt;
| 0x10001 || 1 || 128 || Debug&lt;br /&gt;
|-&lt;br /&gt;
| 0x10201 || 1 || 129 || NoThread&lt;br /&gt;
|-&lt;br /&gt;
| 0x10401 || 1 || 130 || UnknownThread&lt;br /&gt;
|-&lt;br /&gt;
| 0x10601 || 1 || 131 || PortClosed&lt;br /&gt;
|-&lt;br /&gt;
| 0x10801 || 1 || 132 || LimitReached&lt;br /&gt;
|-&lt;br /&gt;
| 0x10A01 || 1 || 133 || InvalidMemoryPool&lt;br /&gt;
|-&lt;br /&gt;
| 0x20401 || 1 || 258 || ReceiveListBroken&lt;br /&gt;
|-&lt;br /&gt;
| 0x20601 || 1 || 259 || OutOfAddressSpace&lt;br /&gt;
|-&lt;br /&gt;
| 0x20801 || 1 || 260 || MessageTooLarge&lt;br /&gt;
|-&lt;br /&gt;
| 0x40001 || 1 || 512 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x40201 || 1 || 513 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x40401 || 1 || 514 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x40601 || 1 || 515 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x40801 || 1 || 516 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x40A01 || 1 || 517 || InvalidProcessId&lt;br /&gt;
|-&lt;br /&gt;
| 0x40C01 || 1 || 518 || InvalidThreadId&lt;br /&gt;
|-&lt;br /&gt;
| 0x40E01 || 1 || 519 || InvalidId&lt;br /&gt;
|-&lt;br /&gt;
| 0x41001 || 1 || 520 || ProcessTerminated&lt;br /&gt;
|-&lt;br /&gt;
| 0x7FE01 || 1 || 1023 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x202 || 2 || 1 || ResultPathNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x402 || 2 || 2 || ResultPathAlreadyExists&lt;br /&gt;
|-&lt;br /&gt;
| 0xE02 || 2 || 7 || ResultTargetLocked&lt;br /&gt;
|-&lt;br /&gt;
| 0x4602 || 2 || 35 || UsableSpaceNotEnoughMmcCalibration&lt;br /&gt;
|-&lt;br /&gt;
| 0x4802 || 2 || 36 || UsableSpaceNotEnoughMmcSafe&lt;br /&gt;
|-&lt;br /&gt;
| 0x4A02 || 2 || 37 || UsableSpaceNotEnoughMmcUser&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C02 || 2 || 38 || UsableSpaceNotEnoughMmcSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x4E02 || 2 || 39 || ResultUsableSpaceNotEnoughSdCard&lt;br /&gt;
|-&lt;br /&gt;
| 0x6402 || 2 || 50 || ResultUnsupportedSdkVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0x7802 || 2 || 60 || ResultMountNameAlreadyExists&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D202 || 2 || 1001 || ResultPartitionNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D402 || 2 || 1002 || ResultTargetNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0xFA202 || 2 || 2001 || PortSdCardNoDevice&lt;br /&gt;
|-&lt;br /&gt;
| 0x13B002 || 2 || 2520 || GameCardCardNotInserted&lt;br /&gt;
|-&lt;br /&gt;
| 0x13B402 || 2 || 2522 || GameCardCardNotActivated&lt;br /&gt;
|-&lt;br /&gt;
| 0x13D802 || 2 || 2540 || GameCardInvalidSecureAccess&lt;br /&gt;
|-&lt;br /&gt;
| 0x13DA02 || 2 || 2541 || GameCardInvalidNormalAccess&lt;br /&gt;
|-&lt;br /&gt;
| 0x13DC02 || 2 || 2542 || GameCardInvalidAccessAcrossMode&lt;br /&gt;
|-&lt;br /&gt;
| 0x13E002 || 2 || 2544 || GameCardInitialDataMismatch&lt;br /&gt;
|-&lt;br /&gt;
| 0x13E202 || 2 || 2545 || GameCardInitialNotFilledWithZero&lt;br /&gt;
|-&lt;br /&gt;
| 0x13E402 || 2 || 2546 || GameCardKekIndexMismatch&lt;br /&gt;
|-&lt;br /&gt;
| 0x13EE02 || 2 || 2551 || GameCardCardHeaderReadFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x145002 || 2 || 2600 || GameCardShouldTransitFromInitialToNormal&lt;br /&gt;
|-&lt;br /&gt;
| 0x145202 || 2 || 2601 || GameCardShouldTransitFromNormalModeToSecure&lt;br /&gt;
|-&lt;br /&gt;
| 0x145402 || 2 || 2602 || GameCardShouldTransitFromNormalModeToDebug&lt;br /&gt;
|-&lt;br /&gt;
| 0x149402 || 2 || 2634 || GameCardSendFirmwareFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x149A02 || 2 || 2637 || GameCardReceiveCertificateFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14A002 || 2 || 2640 || GameCardSendSocCertificateFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14AA02 || 2 || 2645 || GameCardReceiveRandomValueFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14AC02 || 2 || 2646 || GameCardSendRandomValueFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14B602 || 2 || 2651 || GameCardReceiveDeviceChallengeFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14B802 || 2 || 2652 || GameCardRespondDeviceChallengeFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14BA02 || 2 || 2653 || GameCardSendHostChallengeFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14BC02 || 2 || 2654 || GameCardReceiveChallengeResponseFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14BE02 || 2 || 2655 || GameCardChallengeAndResponseFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14D802 || 2 || 2668 || GameCardSplGenerateRandomBytesFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14DE02 || 2 || 2671 || GameCardReadRegisterFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14E002 || 2 || 2672 || GameCardWriteRegisterFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14E202 || 2 || 2673 || GameCardEnableCardBusFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14E402 || 2 || 2674 || GameCardGetCardHeaderFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14E602 || 2 || 2675 || GameCardAsicStatusError&lt;br /&gt;
|-&lt;br /&gt;
| 0x14E802 || 2 || 2676 || GameCardChangeGcModeToSecureFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14EA02 || 2 || 2677 || GameCardChangeGcModeToDebugFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x14EC02 || 2 || 2678 || GameCardReadRmaInfoFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x150802 || 2 || 2692 || GameCardStateCardSecureModeRequired&lt;br /&gt;
|-&lt;br /&gt;
| 0x150A02 || 2 || 2693 || GameCardStateCardDebugModeRequired&lt;br /&gt;
|-&lt;br /&gt;
| 0x155602 || 2 || 2731 || GameCardCommandReadId1Failure&lt;br /&gt;
|-&lt;br /&gt;
| 0x155802 || 2 || 2732 || GameCardCommandReadId2Failure&lt;br /&gt;
|-&lt;br /&gt;
| 0x155A02 || 2 || 2733 || GameCardCommandReadId3Failure&lt;br /&gt;
|-&lt;br /&gt;
| 0x155E02 || 2 || 2735 || GameCardCommandReadPageFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x156202 || 2 || 2737 || GameCardCommandWritePageFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x156402 || 2 || 2738 || GameCardCommandRefreshFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x156C02 || 2 || 2742 || GameCardCommandReadCrcFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x156E02 || 2 || 2743 || GameCardCommandEraseFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x157002 || 2 || 2744 || GameCardCommandReadDevParamFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x157202 || 2 || 2745 || GameCardCommandWriteDevParamFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x16B002 || 2 || 2904 || GameCardDebugCardReceivedIdMismatch&lt;br /&gt;
|-&lt;br /&gt;
| 0x16B202 || 2 || 2905 || GameCardDebugCardId1Mismatch&lt;br /&gt;
|-&lt;br /&gt;
| 0x16B402 || 2 || 2906 || GameCardDebugCardId2Mismatch&lt;br /&gt;
|-&lt;br /&gt;
| 0x171402 || 2 || 2954 || GameCardFsCheckHandleInGetStatusFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x172002 || 2 || 2960 || GameCardFsCheckHandleInCreateReadOnlyFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x172202 || 2 || 2961 || GameCardFsCheckHandleInCreateSecureReadOnlyFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x177202 || 2 || 3001 || ResultNotImplemented&lt;br /&gt;
|-&lt;br /&gt;
| 0x177602 || 2 || 3003 || ResultAlreadyExists&lt;br /&gt;
|-&lt;br /&gt;
| 0x177A02 || 2 || 3005 || ResultOutOfRange&lt;br /&gt;
|-&lt;br /&gt;
| 0x190202 || 2 || 3201 || AllocationMemoryFailedInFatFileSystemA&lt;br /&gt;
|-&lt;br /&gt;
| 0x190402 || 2 || 3202 || AllocationMemoryFailedInFatFileSystemB&lt;br /&gt;
|-&lt;br /&gt;
| 0x190602 || 2 || 3203 || AllocationMemoryFailedInFatFileSystemC&lt;br /&gt;
|-&lt;br /&gt;
| 0x190802 || 2 || 3204 || AllocationMemoryFailedInFatFileSystemD&lt;br /&gt;
|-&lt;br /&gt;
| 0x190A02 || 2 || 3205 || AllocationMemoryFailedInFatFileSystemE&lt;br /&gt;
|-&lt;br /&gt;
| 0x190C02 || 2 || 3206 || AllocationMemoryFailedInFatFileSystemF&lt;br /&gt;
|-&lt;br /&gt;
| 0x190E02 || 2 || 3207 || AllocationMemoryFailedInFatFileSystemG&lt;br /&gt;
|-&lt;br /&gt;
| 0x191002 || 2 || 3208 || AllocationMemoryFailedInFatFileSystemH&lt;br /&gt;
|-&lt;br /&gt;
| 0x195802 || 2 || 3244 || AllocationMemoryFailedInSdCardA&lt;br /&gt;
|-&lt;br /&gt;
| 0x195A02 || 2 || 3245 || AllocationMemoryFailedInSdCardB&lt;br /&gt;
|-&lt;br /&gt;
| 0x195C02 || 2 || 3246 || AllocationMemoryFailedInSystemSaveDataA&lt;br /&gt;
|-&lt;br /&gt;
| 0x195E02 || 2 || 3247 || AllocationMemoryFailedInRomFsFileSystemA&lt;br /&gt;
|-&lt;br /&gt;
| 0x196002 || 2 || 3248 || AllocationMemoryFailedInRomFsFileSystemB&lt;br /&gt;
|-&lt;br /&gt;
| 0x196202 || 2 || 3249 || AllocationMemoryFailedInRomFsFileSystemC&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A3E02 || 2 || 3359 || AllocationMemoryFailedInSdmmcStorageServiceA&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A4002 || 2 || 3360 || AllocationMemoryFailedInBuiltInStorageCreatorA&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A4A02 || 2 || 3365 || AllocationMemoryFailedInRegisterA&lt;br /&gt;
|-&lt;br /&gt;
| 0x21BC02 || 2 || 4318 || IncorrectSaveDataFileSystemMagicCode&lt;br /&gt;
|-&lt;br /&gt;
| 0x234202 || 2 || 4513 || InvalidAcidFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x234402 || 2 || 4514 || InvalidAcidSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x234602 || 2 || 4515 || InvalidAcid&lt;br /&gt;
|-&lt;br /&gt;
| 0x234802 || 2 || 4516 || AcidVerificationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x234A02 || 2 || 4517 || InvalidNcaSignature&lt;br /&gt;
|-&lt;br /&gt;
| 0x234C02 || 2 || 4518 || NcaHeaderSignature1VerificationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x234E02 || 2 || 4519 || NcaHeaderSignature2VerificationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x235002 || 2 || 4520 || NcaFsHeaderHashVerificationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x235202 || 2 || 4521 || InvalidNcaKeyIndex&lt;br /&gt;
|-&lt;br /&gt;
| 0x235602 || 2 || 4523 || InvalidNcaFsHeaderEncryptionType&lt;br /&gt;
|-&lt;br /&gt;
| 0x235802 || 2 || 4524 || InvalidNcaPatchInfoIndirectSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x235A02 || 2 || 4525 || InvalidNcaPatchInfoAesCtrExSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x235C02 || 2 || 4526 || InvalidNcaPatchInfoAesCtrExOffset&lt;br /&gt;
|-&lt;br /&gt;
| 0x235E02 || 2 || 4527 || InvalidNcaId&lt;br /&gt;
|-&lt;br /&gt;
| 0x236002 || 2 || 4528 || InvalidNcaHeader&lt;br /&gt;
|-&lt;br /&gt;
| 0x236202 || 2 || 4529 || InvalidNcaFsHeader&lt;br /&gt;
|-&lt;br /&gt;
| 0x236802 || 2 || 4532 || InvalidHierarchicalSha256BlockSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x236A02 || 2 || 4533 || InvalidHierarchicalSha256LayerCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x236C02 || 2 || 4534 || HierarchicalSha256BaseStorageTooLarge&lt;br /&gt;
|-&lt;br /&gt;
| 0x236E02 || 2 || 4535 || HierarchicalSha256HashVerificationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x244402 || 2 || 4642 || InvalidSha256PartitionHashTarget&lt;br /&gt;
|-&lt;br /&gt;
| 0x244602 || 2 || 4643 || Sha256PartitionHashVerificationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x244802 || 2 || 4644 || PartitionSignatureVerificationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x244A02 || 2 || 4645 || Sha256PartitionSignatureVerificationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x244C02 || 2 || 4646 || InvalidPartitionEntryOffset&lt;br /&gt;
|-&lt;br /&gt;
| 0x244E02 || 2 || 4647 || InvalidSha256PartitionMetaDataSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x249802 || 2 || 4684 || InvalidFatFileNumber&lt;br /&gt;
|-&lt;br /&gt;
| 0x249C02 || 2 || 4686 || InvalidFatFormatBisUser&lt;br /&gt;
|-&lt;br /&gt;
| 0x249E02 || 2 || 4687 || InvalidFatFormatBisSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x24A002 || 2 || 4688 || InvalidFatFormatBisSafe&lt;br /&gt;
|-&lt;br /&gt;
| 0x24A202 || 2 || 4689 || InvalidFatFormatBisCalibration&lt;br /&gt;
|-&lt;br /&gt;
| 0x250E02 || 2 || 4743 || AesXtsFileSystemFileHeaderCorruptedOnFileOpen&lt;br /&gt;
|-&lt;br /&gt;
| 0x251002 || 2 || 4744 || AesXtsFileSystemFileNoHeaderOnFileOpen&lt;br /&gt;
|-&lt;br /&gt;
| 0x280202 || 2 || 5121 || FatFsFormatUnsupportedSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x280402 || 2 || 5122 || FatFsFormatInvalidBpb&lt;br /&gt;
|-&lt;br /&gt;
| 0x280602 || 2 || 5123 || FatFsFormatInvalidParameter&lt;br /&gt;
|-&lt;br /&gt;
| 0x280802 || 2 || 5124 || FatFsFormatIllegalSectorsA&lt;br /&gt;
|-&lt;br /&gt;
| 0x280A02 || 2 || 5125 || FatFsFormatIllegalSectorsB&lt;br /&gt;
|-&lt;br /&gt;
| 0x280C02 || 2 || 5126 || FatFsFormatIllegalSectorsC&lt;br /&gt;
|-&lt;br /&gt;
| 0x280E02 || 2 || 5127 || FatFsFormatIllegalSectorsD&lt;br /&gt;
|-&lt;br /&gt;
| 0x296A02 || 2 || 5301 || UnexpectedInMountTableA&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EE002 || 2 || 6000 || ResultPreconditionViolation&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EE202 || 2 || 6001 || ResultInvalidArgument&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EE402 || 2 || 6002 || ResultInvalidPath&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EE602 || 2 || 6003 || ResultTooLongPath&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EE802 || 2 || 6004 || ResultInvalidCharacter&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EEA02 || 2 || 6005 || ResultInvalidPathFormat&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EEC02 || 2 || 6006 || ResultDirectoryUnobtainable&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EEE02 || 2 || 6007 || ResultNotNormalized&lt;br /&gt;
|-&lt;br /&gt;
| 0x2F5A02 || 2 || 6061 || ResultInvalidOffset&lt;br /&gt;
|-&lt;br /&gt;
| 0x2F5C02 || 2 || 6062 || ResultInvalidSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x2F5E02 || 2 || 6063 || ResultNullptrArgument&lt;br /&gt;
|-&lt;br /&gt;
| 0x2F6002 || 2 || 6064 || ResultInvalidAlignment&lt;br /&gt;
|-&lt;br /&gt;
| 0x2F6202 || 2 || 6065 || ResultInvalidMountName&lt;br /&gt;
|-&lt;br /&gt;
| 0x2F6402 || 2 || 6066 || ResultExtensionSizeTooLarge&lt;br /&gt;
|-&lt;br /&gt;
| 0x2F6602 || 2 || 6067 || ResultExtensionSizeInvalid&lt;br /&gt;
|-&lt;br /&gt;
| 0x307202 || 2 || 6201 || ResultFileExtensionWithoutOpenModeAllowAppend&lt;br /&gt;
|-&lt;br /&gt;
| 0x313A02 || 2 || 6301 || UnsupportedCommitTarget&lt;br /&gt;
|-&lt;br /&gt;
| 0x313C02 || 2 || 6302 || UnsupportedSetSizeForNotResizableSubStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x313E02 || 2 || 6303 || UnsupportedSetSizeForResizableSubStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x314002 || 2 || 6304 || UnsupportedSetSizeForMemoryStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x314202 || 2 || 6305 || UnsupportedOperateRangeForMemoryStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x314402 || 2 || 6306 || UnsupportedOperateRangeForFileStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x314602 || 2 || 6307 || UnsupportedOperateRangeForFileHandleStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x314802 || 2 || 6308 || UnsupportedOperateRangeForSwitchStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x314A02 || 2 || 6309 || UnsupportedOperateRangeForStorageServiceObjectAdapter&lt;br /&gt;
|-&lt;br /&gt;
| 0x314C02 || 2 || 6310 || UnsupportedWriteForAesCtrCounterExtendedStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x314E02 || 2 || 6311 || UnsupportedSetSizeForAesCtrCounterExtendedStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x315002 || 2 || 6312 || UnsupportedOperateRangeForAesCtrCounterExtendedStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x315202 || 2 || 6313 || UnsupportedWriteForAesCtrStorageExternal&lt;br /&gt;
|-&lt;br /&gt;
| 0x315402 || 2 || 6314 || UnsupportedSetSizeForAesCtrStorageExternal&lt;br /&gt;
|-&lt;br /&gt;
| 0x315602 || 2 || 6315 || UnsupportedSetSizeForAesCtrStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x315802 || 2 || 6316 || UnsupportedSetSizeForHierarchicalIntegrityVerificationStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x315A02 || 2 || 6317 || UnsupportedOperateRangeForHierarchicalIntegrityVerificationStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x315C02 || 2 || 6318 || UnsupportedSetSizeForIntegrityVerificationStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x315E02 || 2 || 6319 || UnsupportedOperateRangeForWritableIntegrityVerificationStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x316002 || 2 || 6320 || UnsupportedOperateRangeForIntegrityVerificationStorage &lt;br /&gt;
|-&lt;br /&gt;
| 0x316202 || 2 || 6321 || UnsupportedSetSizeForBlockCacheBufferedStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x316402 || 2 || 6322 || UnsupportedOperateRangeForWritableBlockCacheBufferedStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x316602 || 2 || 6323 || UnsupportedOperateRangeForBlockCacheBufferedStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x316802 || 2 || 6324 || UnsupportedWriteForIndirectStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x316A02 || 2 || 6325 || UnsupportedSetSizeForIndirectStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x316C02 || 2 || 6326 || UnsupportedOperateRangeForIndirectStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x316E02 || 2 || 6327 || UnsupportedWriteForZeroStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x317002 || 2 || 6328 || UnsupportedSetSizeForZeroStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x317202 || 2 || 6329 || UnsupportedSetSizeForHierarchicalSha256Storage&lt;br /&gt;
|-&lt;br /&gt;
| 0x317402 || 2 || 6330 || UnsupportedWriteForReadOnlyBlockCacheStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x317602 || 2 || 6331 || UnsupportedSetSizeForReadOnlyBlockCacheStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x317802 || 2 || 6332 || UnsupportedSetSizeForIntegrityRomFsStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x317A02 || 2 || 6333 || UnsupportedSetSizeForDuplexStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x317C02 || 2 || 6334 || UnsupportedOperateRangeForDuplexStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x317E02 || 2 || 6335 || UnsupportedSetSizeForHierarchicalDuplexStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x318002 || 2 || 6336 || UnsupportedGetSizeForRemapStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x318202 || 2 || 6337 || UnsupportedSetSizeForRemapStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x318402 || 2 || 6338 || UnsupportedOperateRangeForRemapStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x318602 || 2 || 6339 || UnsupportedSetSizeForIntegritySaveDataStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x318802 || 2 || 6340 || UnsupportedOperateRangeForIntegritySaveDataStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x318A02 || 2 || 6341 || UnsupportedSetSizeForJournalIntegritySaveDataStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x318C02 || 2 || 6342 || UnsupportedOperateRangeForJournalIntegritySaveDataStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x318E02 || 2 || 6343 || UnsupportedGetSizeForJournalStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x319002 || 2 || 6344 || UnsupportedSetSizeForJournalStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x319202 || 2 || 6345 || UnsupportedOperateRangeForJournalStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x319402 || 2 || 6346 || UnsupportedSetSizeForUnionStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x319602 || 2 || 6347 || UnsupportedSetSizeForAllocationTableStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x319802 || 2 || 6348 || UnsupportedReadForWriteOnlyGameCardStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x319A02 || 2 || 6349 || UnsupportedSetSizeForWriteOnlyGameCardStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x319C02 || 2 || 6350 || UnsupportedWriteForReadOnlyGameCardStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x319E02 || 2 || 6351 || UnsupportedSetSizeForReadOnlyGameCardStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x31A002 || 2 || 6352 || UnsupportedOperateRangeForReadOnlyGameCardStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x31A202 || 2 || 6353 || UnsupportedSetSizeForSdmmcStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x31A402 || 2 || 6354 || UnsupportedOperateRangeForSdmmcStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x31A602 || 2 || 6355 || UnsupportedOperateRangeForFatFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31A802 || 2 || 6356 || UnsupportedOperateRangeForStorageFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31AA02 || 2 || 6357 || UnsupportedSetSizeForInternalStorageConcatenationFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31AC02 || 2 || 6358 || UnsupportedOperateRangeForInternalStorageConcatenationFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31AE02 || 2 || 6359 || UnsupportedQueryEntryForConcatenationFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31B002 || 2 || 6360 || UnsupportedOperateRangeForConcatenationFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31B202 || 2 || 6361 || UnsupportedSetSizeForZeroBitmapFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31B402 || 2 || 6362 || UnsupportedOperateRangeForFileServiceObjectAdapter&lt;br /&gt;
|-&lt;br /&gt;
| 0x31B602 || 2 || 6363 || UnsupportedOperateRangeForAesXtsFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31B802 || 2 || 6364 || UnsupportedWriteForRomFsFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31BA02 || 2 || 6365 || UnsupportedCommitProvisionallyForRomFsFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31BC02 || 2 || 6366 || UnsupportedGetTotalSpaceSizeForRomFsFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31BE02 || 2 || 6367 || UnsupportedWriteForRomFsFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31C002 || 2 || 6368 || UnsupportedOperateRangeForRomFsFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31C202 || 2 || 6369 || UnsupportedWriteForReadOnlyFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31C402 || 2 || 6370 || UnsupportedCommitProvisionallyForReadOnlyFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31C602 || 2 || 6371 || UnsupportedGetTotalSpaceSizeForReadOnlyFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31C802 || 2 || 6372 || UnsupportedWriteForReadOnlyFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31CA02 || 2 || 6373 || UnsupportedOperateRangeForReadOnlyFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31CC02 || 2 || 6374 || UnsupportedWriteForPartitionFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31CE02 || 2 || 6375 || UnsupportedCommitProvisionallyForPartitionFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31D002 || 2 || 6376 || UnsupportedWriteForPartitionFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31D202 || 2 || 6377 || UnsupportedOperateRangeForPartitionFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31D402 || 2 || 6378 || UnsupportedOperateRangeForTmFileSystemFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31D602 || 2 || 6379 || UnsupportedWriteForSaveDataInternalStorageFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31DC02 || 2 || 6382 || UnsupportedCommitProvisionallyForApplicationTemporaryFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31DE02 || 2 || 6383 || UnsupportedCommitProvisionallyForSaveDataFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31E002 || 2 || 6384 || UnsupportedCommitProvisionallyForDirectorySaveDataFileSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x31E202 || 2 || 6385 || UnsupportedWriteForZeroBitmapHashStorageFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x31E402 || 2 || 6386 || UnsupportedSetSizeForZeroBitmapHashStorageFile&lt;br /&gt;
|-&lt;br /&gt;
| 0x326602 || 2 || 6451 || ResultNcaExternalKeyUnregisteredDeprecated&lt;br /&gt;
|-&lt;br /&gt;
| 0x326E02 || 2 || 6455 || ResultFileNotClosed&lt;br /&gt;
|-&lt;br /&gt;
| 0x327002 || 2 || 6456 || ResultDirectoryNotClosed&lt;br /&gt;
|-&lt;br /&gt;
| 0x327202 || 2 || 6457 || ResultWriteModeFileNotClosed&lt;br /&gt;
|-&lt;br /&gt;
| 0x327402 || 2 || 6458 || ResultAllocatorAlreadyRegistered&lt;br /&gt;
|-&lt;br /&gt;
| 0x327602 || 2 || 6459 || ResultDefaultAllocatorAlreadyUsed&lt;br /&gt;
|-&lt;br /&gt;
| 0x327A02 || 2 || 6461 || ResultAllocatorAlignmentViolation&lt;br /&gt;
|-&lt;br /&gt;
| 0x328202 || 2 || 6465 || ResultUserNotExist&lt;br /&gt;
|-&lt;br /&gt;
| 0x339402 || 2 || 6602 || FileNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x339602 || 2 || 6603 || DirectoryNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x346402 || 2 || 6706 || MappingTableFull&lt;br /&gt;
|-&lt;br /&gt;
| 0x346A02 || 2 || 6709 || OpenCountLimit&lt;br /&gt;
|-&lt;br /&gt;
| 0x346C02 || 2 || 6710 || MultiCommitFileSystemLimit&lt;br /&gt;
|-&lt;br /&gt;
| 0x353602 || 2 || 6811 || MapFull&lt;br /&gt;
|-&lt;br /&gt;
| 0x35F202 || 2 || 6905 || NotMounted&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DBC02 || 2 || 7902 || DbmKeyNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DBE02 || 2 || 7903 || DbmFileNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DC002 || 2 || 7904 || DbmDirectoryNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DC402 || 2 || 7906 || DbmAlreadyExists&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DC602 || 2 || 7907 || DbmKeyFull&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DC802 || 2 || 7908 || DbmDirectoryEntryFull&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DCA02 || 2 || 7909 || DbmFileEntryFull&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DD402 || 2 || 7914 || DbmInvalidOperation&lt;br /&gt;
|-&lt;br /&gt;
| 0x203 || 3 || 1 || ResultNoPermission&lt;br /&gt;
|-&lt;br /&gt;
| 0x403 || 3 || 2 || ResultAccessViolation&lt;br /&gt;
|-&lt;br /&gt;
| 0x603 || 3 || 3 || ResultBadRequest&lt;br /&gt;
|-&lt;br /&gt;
| 0x803 || 3 || 4 || ResultBusy&lt;br /&gt;
|-&lt;br /&gt;
| 0xA03 || 3 || 5 || ResultDeadlock&lt;br /&gt;
|-&lt;br /&gt;
| 0xC03 || 3 || 6 || ResultInvalidAddress&lt;br /&gt;
|-&lt;br /&gt;
| 0xE03 || 3 || 7 || ResultInvalidParameter&lt;br /&gt;
|-&lt;br /&gt;
| 0x1003 || 3 || 8 || ResultOutOfMemory&lt;br /&gt;
|-&lt;br /&gt;
| 0x1203 || 3 || 9 || ResultOutOfResource&lt;br /&gt;
|-&lt;br /&gt;
| 0x3EA03 || 3 || 501 || InvalidHandle&lt;br /&gt;
|-&lt;br /&gt;
| 0x3EC03 || 3 || 502 || InvalidCurrentMemoryState&lt;br /&gt;
|-&lt;br /&gt;
| 0x3EE03 || 3 || 503 || InvalidTransferMemoryState&lt;br /&gt;
|-&lt;br /&gt;
| 0x3F003 || 3 || 504 || InvalidTransferMemorySize&lt;br /&gt;
|-&lt;br /&gt;
| 0x3F203 || 3 || 505 || InvalidSharedMemoryState&lt;br /&gt;
|-&lt;br /&gt;
| 0x3F403 || 3 || 506 || InvalidSharedMemorySize&lt;br /&gt;
|-&lt;br /&gt;
| 0x7FE03 || 3 || 1023 || ResultInternalError&lt;br /&gt;
|-&lt;br /&gt;
| 0xA05 || 5 || 5 || ContentNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0xE05 || 5 || 7 || ContentMetaNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x1805 || 5 || 12 || UnknownStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0xDC05 || 5 || 110 || InvalidContentMetaDatabase&lt;br /&gt;
|-&lt;br /&gt;
| 0x17C05 || 5 || 190 || WriteToReadOnlyContentStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x806 || 6 || 4 || InvalidMemoryState&lt;br /&gt;
|-&lt;br /&gt;
| 0x1006 || 6 || 8 || InvalidHandle&lt;br /&gt;
|-&lt;br /&gt;
| 0x408 || 8 || 2 || ProgramNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x608 || 8 || 3 || DataNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x808 || 8 || 4 || UnknownResolver&lt;br /&gt;
|-&lt;br /&gt;
| 0xA08 || 8 || 5 || ApplicationNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0xC08 || 8 || 6 || HtmlDocumentNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0xE08 || 8 || 7 || AddOnContentNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x1008 || 8 || 8 || ControlNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x1208 || 8 || 9 || LegalInformationNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x1408 || 8 || 10 || DebugProgramNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x209 || 9 || 1 || ArgumentOverflow&lt;br /&gt;
|-&lt;br /&gt;
| 0x409 || 9 || 2 || ArgumentCountOverflow&lt;br /&gt;
|-&lt;br /&gt;
| 0x609 || 9 || 3 || MetaOverflow&lt;br /&gt;
|-&lt;br /&gt;
| 0x809 || 9 || 4 || InvalidMeta&lt;br /&gt;
|-&lt;br /&gt;
| 0xA09 || 9 || 5 || InvalidNso&lt;br /&gt;
|-&lt;br /&gt;
| 0xC09 || 9 || 6 || InvalidPath&lt;br /&gt;
|-&lt;br /&gt;
| 0xE09 || 9 || 7 || MaxProcess&lt;br /&gt;
|-&lt;br /&gt;
| 0x1009 || 9 || 8 || NotPinned&lt;br /&gt;
|-&lt;br /&gt;
| 0x1209 || 9 || 9 || InvalidProgramId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1409 || 9 || 10 || InvalidVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0x1609 || 9 || 11 || InvalidAcidSignature&lt;br /&gt;
|-&lt;br /&gt;
| 0x1809 || 9 || 12 || InvalidNcaSignature&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C09 || 9 || 14 || InvalidPlatformId&lt;br /&gt;
|-&lt;br /&gt;
| 0x6609 || 9 || 51 || OutOfAddressSpace&lt;br /&gt;
|-&lt;br /&gt;
| 0x6809 || 9 || 52 || InvalidNroImage&lt;br /&gt;
|-&lt;br /&gt;
| 0x6A09 || 9 || 53 || InvalidNrrImage&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C09 || 9 || 54 || NotAuthorized&lt;br /&gt;
|-&lt;br /&gt;
| 0x6E09 || 9 || 55 || MaxModule&lt;br /&gt;
|-&lt;br /&gt;
| 0x7009 || 9 || 56 || MaxRegistration&lt;br /&gt;
|-&lt;br /&gt;
| 0x7209 || 9 || 57 || NroAlreadyLoaded&lt;br /&gt;
|-&lt;br /&gt;
| 0xA209 || 9 || 81 || InvalidAddress&lt;br /&gt;
|-&lt;br /&gt;
| 0xA409 || 9 || 82 || InvalidSize&lt;br /&gt;
|-&lt;br /&gt;
| 0xA609 || 9 || 83 || InvalidCurrentMemory&lt;br /&gt;
|-&lt;br /&gt;
| 0xA809 || 9 || 84 || NotLoaded&lt;br /&gt;
|-&lt;br /&gt;
| 0xAA09 || 9 || 85 || NotRegistered&lt;br /&gt;
|-&lt;br /&gt;
| 0xAC09 || 9 || 86 || InvalidSession&lt;br /&gt;
|-&lt;br /&gt;
| 0xAE09 || 9 || 87 || InvalidProcess&lt;br /&gt;
|-&lt;br /&gt;
| 0xC809 || 9 || 100 || UnknownCapability&lt;br /&gt;
|-&lt;br /&gt;
| 0xCE09 || 9 || 103 || InvalidCapabilityKernelFlags&lt;br /&gt;
|-&lt;br /&gt;
| 0xD009 || 9 || 104 || InvalidCapabilitySyscallMask&lt;br /&gt;
|-&lt;br /&gt;
| 0xD409 || 9 || 106 || InvalidCapabilityMapRange&lt;br /&gt;
|-&lt;br /&gt;
| 0xD609 || 9 || 107 || InvalidCapabilityMapPage&lt;br /&gt;
|-&lt;br /&gt;
| 0xDE09 || 9 || 111 || InvalidCapabilityInterruptPair&lt;br /&gt;
|-&lt;br /&gt;
| 0xE209 || 9 || 113 || InvalidCapabilityApplicationType&lt;br /&gt;
|-&lt;br /&gt;
| 0xE409 || 9 || 114 || InvalidCapabilityKernelVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0xE609 || 9 || 115 || InvalidCapabilityHandleTable&lt;br /&gt;
|-&lt;br /&gt;
| 0xE809 || 9 || 116 || InvalidCapabilityDebugFlags&lt;br /&gt;
|-&lt;br /&gt;
| 0x19009 || 9 || 200 || InternalError&lt;br /&gt;
|-&lt;br /&gt;
| 0x1940A || 10 || 202 || InvalidCmifHeaderSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A60A || 10 || 211 || InvalidCmifInHeader&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A80A || 10 || 212 || InvalidCmifOutHeader&lt;br /&gt;
|-&lt;br /&gt;
| 0x1BA0A || 10 || 221 || UnknownMethodId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D60A || 10 || 235 || InvalidInObjectCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D80A || 10 || 236 || InvalidOutObjectCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x25A0A || 10 || 301 || OutOfDomainEntry&lt;br /&gt;
|-&lt;br /&gt;
| 0x20B || 11 || 1 || NotSupported&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC0B || 11 || 102 || OutOfSessionMemory&lt;br /&gt;
|-&lt;br /&gt;
| 0x11A0B || 11 || 141 || InsufficientPointerTransferBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0x1900B || 11 || 200 || OutOfDomains&lt;br /&gt;
|-&lt;br /&gt;
| 0x25A0B || 11 || 301 || SessionClosed&lt;br /&gt;
|-&lt;br /&gt;
| 0x3240B || 11 || 402 || InvalidRequestSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x3260B || 11 || 403 || UnknownCommandType&lt;br /&gt;
|-&lt;br /&gt;
| 0x3D60B || 11 || 491 || TargetNotDomain&lt;br /&gt;
|-&lt;br /&gt;
| 0x20F || 15 || 1 || ProcessNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x60F || 15 || 3 || NotTerminated&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0F || 15 || 5 || ApplicationRunning&lt;br /&gt;
|-&lt;br /&gt;
| 0x410 || 16 || 2 || Title-id not found.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6E10 || 16 || 55 || Unexpected [[NACP#TitlesDataFormat|TitlesDataFormat]].&lt;br /&gt;
|-&lt;br /&gt;
| 0xF010 || 16 || 120 || Sysupdate not required.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F610 || 16 || 251 || Unexpected StorageId.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A810 || 16 || 340 || [[Network_Interface_services#IsAnyInternetRequestAccepted|IsAnyInternetRequestAccepted]] with the output from [[#Network_Interface_services#GetClientId|GetClientId]] returned false.&lt;br /&gt;
|-&lt;br /&gt;
| 0x64210 || 16 || 801 || [[NS_Services#SystemDeliveryInfo|SystemDeliveryInfo]] system_delivery_protocol_version is less than the system-setting.&lt;br /&gt;
|-&lt;br /&gt;
| 0x64410 || 16 || 802 || [[NS_Services#SystemDeliveryInfo|SystemDeliveryInfo]] system_delivery_protocol_version is larger than the system-setting.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6F810 || 16 || 892 || RequestServerStopper state ref-count is zero.&lt;br /&gt;
|-&lt;br /&gt;
| 0x74610 || 16 || 931 || Invalid [[NS_Services#SystemDeliveryInfo|SystemDeliveryInfo]] HMAC / invalid Meta Id.&lt;br /&gt;
|-&lt;br /&gt;
| 0x215 || 21 || 1 || OutOfProcesses&lt;br /&gt;
|-&lt;br /&gt;
| 0x415 || 21 || 2 || InvalidClient&lt;br /&gt;
|-&lt;br /&gt;
| 0x615 || 21 || 3 || OutOfSessions&lt;br /&gt;
|-&lt;br /&gt;
| 0x815 || 21 || 4 || AlreadyRegistered&lt;br /&gt;
|-&lt;br /&gt;
| 0xA15 || 21 || 5 || OutOfServices&lt;br /&gt;
|-&lt;br /&gt;
| 0xC15 || 21 || 6 || InvalidServiceName&lt;br /&gt;
|-&lt;br /&gt;
| 0xE15 || 21 || 7 || NotRegistered&lt;br /&gt;
|-&lt;br /&gt;
| 0x1015 || 21 || 8 || NotAllowed&lt;br /&gt;
|-&lt;br /&gt;
| 0x1215 || 21 || 9 || TooLargeAccessControl&lt;br /&gt;
|-&lt;br /&gt;
| 0x416 || 22 || 2 || ResultOutOfAddressSpace&lt;br /&gt;
|-&lt;br /&gt;
| 0x616 || 22 || 3 || ResultNroAlreadyLoaded&lt;br /&gt;
|-&lt;br /&gt;
| 0x816 || 22 || 4 || ResultInvalidNroImage&lt;br /&gt;
|-&lt;br /&gt;
| 0xC16 || 22 || 6 || ResultInvalidNrrImage&lt;br /&gt;
|-&lt;br /&gt;
| 0x1016 || 22 || 8 || ResultMaxRegistration&lt;br /&gt;
|-&lt;br /&gt;
| 0x1216 || 22 || 9 || ResultNotAuthorized&lt;br /&gt;
|-&lt;br /&gt;
| 0x80216 || 22 || 1025 || InvalidAddress&lt;br /&gt;
|-&lt;br /&gt;
| 0x80416 || 22 || 1026 || InvalidSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80816 || 22 || 1028 || NotLoaded&lt;br /&gt;
|-&lt;br /&gt;
| 0x80A16 || 22 || 1029 || NotRegistered&lt;br /&gt;
|-&lt;br /&gt;
| 0x80C16 || 22 || 1030 || InvalidSession&lt;br /&gt;
|-&lt;br /&gt;
| 0x80E16 || 22 || 1031 || InvalidProcess&lt;br /&gt;
|-&lt;br /&gt;
| 0x21A || 26 || 1 || SecureMonitorNotImplemented&lt;br /&gt;
|-&lt;br /&gt;
| 0x41A || 26 || 2 || SecureMonitorInvalidArgument&lt;br /&gt;
|-&lt;br /&gt;
| 0x61A || 26 || 3 || SecureMonitorBusy&lt;br /&gt;
|-&lt;br /&gt;
| 0x81A || 26 || 4 || SecureMonitorNoAsyncOperation&lt;br /&gt;
|-&lt;br /&gt;
| 0xA1A || 26 || 5 || SecureMonitorInvalidAsyncOperation&lt;br /&gt;
|-&lt;br /&gt;
| 0xC1A || 26 || 6 || SecureMonitorNotPermitted&lt;br /&gt;
|-&lt;br /&gt;
| 0xC81A || 26 || 100 || InvalidSize&lt;br /&gt;
|-&lt;br /&gt;
| 0xCA1A || 26 || 101 || UnknownSecureMonitorError&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC1A || 26 || 102 || DecryptionFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0xD01A || 26 || 104 || OutOfKeySlots&lt;br /&gt;
|-&lt;br /&gt;
| 0xD21A || 26 || 105 || InvalidKeySlot&lt;br /&gt;
|-&lt;br /&gt;
| 0xD41A || 26 || 106 || BootReasonAlreadySet&lt;br /&gt;
|-&lt;br /&gt;
| 0xD61A || 26 || 107 || BootReasonNotSet&lt;br /&gt;
|-&lt;br /&gt;
| 0xD81A || 26 || 108 || InvalidArgument&lt;br /&gt;
|-&lt;br /&gt;
| 0x1423 || 35 || 10 || Invalid command ID received by tipc processor.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E23 || 35 || 15 || Invalid message format received by tipc processor.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC823 || 35 || 100 || Tipc request was deferred for future processing (internal to the processor, never returned externally).&lt;br /&gt;
|-&lt;br /&gt;
| 0xCA23 || 35 || 101 || Tipc object was closed (via close command 0xF, internal, never returned externally). &lt;br /&gt;
|-&lt;br /&gt;
| 0x19269 || 105 || 201 || SettingsNameNull&lt;br /&gt;
|-&lt;br /&gt;
| 0x19469 || 105 || 202 || SettingsItemKeyNull&lt;br /&gt;
|-&lt;br /&gt;
| 0x19669 || 105 || 203 || SettingsItemValueNull&lt;br /&gt;
|-&lt;br /&gt;
| 0x19A69 || 105 || 205 || SettingsItemValueBufferNull&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A069 || 105 || 208 || Null setting value size buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A269 || 105 || 209 || Null debug mode flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1BA69 || 105 || 221 || SettingsNameEmpty&lt;br /&gt;
|-&lt;br /&gt;
| 0x1BC69 || 105 || 222 || SettingsItemKeyEmpty&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E269 || 105 || 241 || SettingsNameTooLong&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E469 || 105 || 242 || SettingsItemKeyTooLong&lt;br /&gt;
|-&lt;br /&gt;
| 0x20A69 || 105 || 261 || SettingsNameInvalidFormat&lt;br /&gt;
|-&lt;br /&gt;
| 0x20C69 || 105 || 262 || SettingsItemKeyInvalidFormat&lt;br /&gt;
|-&lt;br /&gt;
| 0x4DA69 || 105 || 621 || Null language code buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4E269 || 105 || 625 || Language out of valid range.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4EE69 || 105 || 631 || Null network settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4F069 || 105 || 632 || Null network settings output count buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50269 || 105 || 641 || Null backlight settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x51669 || 105 || 651 || Null Bluetooth device setting buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x51869 || 105 || 652 || Null Bluetooth device setting output count buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x51A69 || 105 || 653 || Null Bluetooth enable flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x51C69 || 105 || 654 || Null Bluetooth AFH enable flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x51E69 || 105 || 655 || Null Bluetooth boost enable flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x52069 || 105 || 656 || Null BLE pairing settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x52269 || 105 || 657 || Null BLE pairing settings entry count buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x52A69 || 105 || 661 || Null external steady clock source ID buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x52C69 || 105 || 662 || Null user system clock context buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x52E69 || 105 || 663 || Null network system clock context buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x53069 || 105 || 664 || Null user system clock automatic correction enabled flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x53269 || 105 || 665 || Null shutdown RTC value buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x53469 || 105 || 666 || Null external steady clock internal offset buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x53E69 || 105 || 671 || Null account settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x55269 || 105 || 681 || Null audio volume buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x55669 || 105 || 683 || Null ForceMuteOnHeadphoneRemoved buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x55869 || 105 || 684 || Null headphone volume warning count buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x55E69 || 105 || 687 || Invalid audio output mode.&lt;br /&gt;
|-&lt;br /&gt;
| 0x56069 || 105 || 688 || Null headphone volume update flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x56669 || 105 || 691 || Null console information upload flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x57A69 || 105 || 701 || Null automatic application download flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x57C69 || 105 || 702 || Null notification settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x57E69 || 105 || 703 || Null account notification settings entry count buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x58069 || 105 || 704 || Null account notification settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x58E69 || 105 || 711 || Null vibration master volume buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x59069 || 105 || 712 || Null NX controller settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x59269 || 105 || 713 || Null NX controller settings entry count buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x59469 || 105 || 714 || Null USB full key enable flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5A269 || 105 || 721 || Null TV settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5A469 || 105 || 722 || Null EDID buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5B669 || 105 || 731 || Null data deletion settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5CA69 || 105 || 741 || Null initial system applet program ID buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5CC69 || 105 || 742 || Null overlay disp program ID buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5CE69 || 105 || 743 || Null IsInRepairProcess buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5D069 || 105 || 744 || Null RequiresRunRepairTimeReviser buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5DE69 || 105 || 751 || Null device timezone location name buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5F269 || 105 || 761 || Null primary album storage buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x60669 || 105 || 771 || Null USB 3.0 enable flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x60869 || 105 || 772 || Null USB Type-C power source circuit version buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x61A69 || 105 || 781 || Null battery lot buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x62E69 || 105 || 791 || Null serial number buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x64269 || 105 || 801 || Null lock screen flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x64669 || 105 || 803 || Null color set ID buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x64869 || 105 || 804 || Null quest flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x64A69 || 105 || 805 || Null wireless certification file size buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x64C69 || 105 || 806 || Null wireless certification file buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x64E69 || 105 || 807 || Null initial launch settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x65069 || 105 || 808 || Null device nickname buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x65269 || 105 || 809 || Null battery percentage flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x65469 || 105 || 810 || Null applet launch flags buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7E869 || 105 || 1012 || Null wireless LAN enable flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7FA69 || 105 || 1021 || Null product model buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x80E69 || 105 || 1031 || Null NFC enable flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x82269 || 105 || 1041 || Null ECI device certificate buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x82469 || 105 || 1042 || Null E-Ticket device certificate buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x83669 || 105 || 1051 || Null sleep settings buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84A69 || 105 || 1061 || Null EULA version buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84C69 || 105 || 1062 || Null EULA version entry count buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x85E69 || 105 || 1071 || Null LDN channel buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x87269 || 105 || 1081 || Null SSL key buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x87469 || 105 || 1082 || Null SSL certificate buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x88669 || 105 || 1091 || Null telemetry flags buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x89A69 || 105 || 1101 || Null Gamecard key buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x89C69 || 105 || 1102 || Null Gamecard certificate buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8AE69 || 105 || 1111 || Null PTM battery lot buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8B069 || 105 || 1112 || Null PTM fuel gauge parameter buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8C269 || 105 || 1121 || Null ECI device key buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8C469 || 105 || 1122 || Null E-Ticket device key buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8D669 || 105 || 1131 || Null speaker parameter buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8EA69 || 105 || 1141 || Null firmware version buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8EC69 || 105 || 1142 || Null firmware version digest buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8EE69 || 105 || 1143 || Null rebootless system update version buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8FE69 || 105 || 1151 || Null Mii author ID buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x91269 || 105 || 1161 || Null fatal flags buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x92669 || 105 || 1171 || Null auto update enable flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x93A69 || 105 || 1181 || Null external RTC reset flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x94E69 || 105 || 1191 || Null push notification activity mode buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x96269 || 105 || 1201 || Null service discovery control setting buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x97669 || 105 || 1211 || Null error report share permission buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x98A69 || 105 || 1221 || Null LCD vendor ID buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x99E69 || 105 || 1231 || Null console SixAxis sensor acceleration bias buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A069 || 105 || 1232 || Null console SixAxis sensor angular velocity bias buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A269 || 105 || 1233 || Null console SixAxis sensor acceleration gain buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A469 || 105 || 1234 || Null console SixAxis sensor angular velocity gain buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A669 || 105 || 1235 || Null console SixAxis sensor angular velocity time bias buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9A869 || 105 || 1236 || Null console SixAxis sensor angular acceleration buffer .&lt;br /&gt;
|-&lt;br /&gt;
| 0x9B269 || 105 || 1241 || Null keyboard layout buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9BA69 || 105 || 1245 || Invalid keyboard layout.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9C669 || 105 || 1251 || Null web inspector flag buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9C869 || 105 || 1252 || Null allowed SSL hosts buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9CA69 || 105 || 1253 || Null allowed SSL hosts entry count buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9CC69 || 105 || 1254 || Null host FS mount point buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9EE69 || 105 || 1271 || Null Amiibo key buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F069 || 105 || 1272 || Null Amiibo ECQV certificate buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F269 || 105 || 1273 || Null Amiibo ECDSA certificate buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F469 || 105 || 1274 || Null Amiibo ECQV BLS key buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F669 || 105 || 1275 || Null Amiibo ECQV BLS certificate buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9F869 || 105 || 1276 || Null Amiibo ECQV BLS root certificate buffer.&lt;br /&gt;
|- &lt;br /&gt;
| 0xF06E || 110 || 120 || Invalid permission.&lt;br /&gt;
|- &lt;br /&gt;
| 0x1906E || 110 || 200 || Wrong input.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8986E || 110 || 1100 || Request failed, network not available, no connection reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x8AE6E || 110 || 1111 || Request failed, WiFi turned off&lt;br /&gt;
|-&lt;br /&gt;
| 0xFA66E || 110 || 2003 || Request failed, network not available, connection reset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18706E || 110 || 3128 || Request failed, network has no internet access&lt;br /&gt;
|-&lt;br /&gt;
| 0x190471 || 113 || 3202 || Device is already disconnected&lt;br /&gt;
|-&lt;br /&gt;
| 0x190A71 || 113 || 3205 || Device is already connected&lt;br /&gt;
|-&lt;br /&gt;
| 0x272 || 114 || 1 || ResultOperationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0xC72 || 114 || 6 || ResultNotSupported&lt;br /&gt;
|-&lt;br /&gt;
| 0x74 || 116 || 0 || ResultNotInitialized&lt;br /&gt;
|-&lt;br /&gt;
| 0x274 || 116 || 1 || ResultNoCapability&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC74 || 116 || 102 || OffsetInvalid&lt;br /&gt;
|-&lt;br /&gt;
| 0xCE74 || 116 || 103 || UninitializedClock&lt;br /&gt;
|-&lt;br /&gt;
| 0x19074 || 116 || 200 || ResultNotComparable&lt;br /&gt;
|-&lt;br /&gt;
| 0x19274 || 116 || 201 || ResultOverflowed&lt;br /&gt;
|-&lt;br /&gt;
| 0x64274 || 116 || 801 || ResultOutOfMemory&lt;br /&gt;
|-&lt;br /&gt;
| 0x70A74 || 116 || 901 || InvalidPointer&lt;br /&gt;
|-&lt;br /&gt;
| 0x70C74 || 116 || 902 || OutOfRange&lt;br /&gt;
|-&lt;br /&gt;
| 0x70E74 || 116 || 903 || InvalidTimeZoneBinary&lt;br /&gt;
|-&lt;br /&gt;
| 0x7BA74 || 116 || 989 || NotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x7BC74 || 116 || 990 || NotImplemented&lt;br /&gt;
|-&lt;br /&gt;
| 0xC79 || 121 || 6 || ResultInternetRequestNotAccepted&lt;br /&gt;
|-&lt;br /&gt;
| 0x27A || 122 || 1 || ResultInvalidArgument&lt;br /&gt;
|-&lt;br /&gt;
| 0x47A || 122 || 2 || ResultNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x67A || 122 || 3 || ResultLocked&lt;br /&gt;
|-&lt;br /&gt;
| 0x87A || 122 || 4 || ResultAlreadyMounted&lt;br /&gt;
|-&lt;br /&gt;
| 0xA7A || 122 || 5 || ResultNotMounted&lt;br /&gt;
|-&lt;br /&gt;
| 0xC7A || 122 || 6 || ResultAlreadyOpened&lt;br /&gt;
|-&lt;br /&gt;
| 0xE7A || 122 || 7 || ResultNotOpened&lt;br /&gt;
|-&lt;br /&gt;
| 0x107A || 122 || 8 || ResultInternetRequestNotAccepted&lt;br /&gt;
|-&lt;br /&gt;
| 0xA07A || 122 || 80 || ResultPassphraseNotSaved&lt;br /&gt;
|-&lt;br /&gt;
| 0xA27A || 122 || 81 || ResultDataVerificationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0xB47A || 122 || 90 || ResultNotPermitted&lt;br /&gt;
|-&lt;br /&gt;
| 0xC47A || 122 || 98 || ResultInvalidOperation&lt;br /&gt;
|-&lt;br /&gt;
| 0x167B || 123 || 11 || ResultErrorLower&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A7B || 123 || 13 || ResultInternalLogicError&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC7B || 123 || 102 || ResultInsufficientMemory&lt;br /&gt;
|-&lt;br /&gt;
| 0xE87B || 123 || 116 || ResultInvalidSocketDescriptor&lt;br /&gt;
|-&lt;br /&gt;
| 0x1027B || 123 || 129 || ResultInvalidCrlFormat&lt;br /&gt;
|-&lt;br /&gt;
| 0x1987B || 123 || 204 || ResultIoWouldBlock&lt;br /&gt;
|-&lt;br /&gt;
| 0x19A7B || 123 || 205 || ResultIoTimeout&lt;br /&gt;
|-&lt;br /&gt;
| 0x19C7B || 123 || 206 || ResultIoAborted&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A07B || 123 || 208 || ResultNoConnection&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A27B || 123 || 209 || ResultConnectionReset&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A47B || 123 || 210 || ResultConnectionAborted&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A67B || 123 || 211 || ResultSocketShutdown&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A87B || 123 || 212 || ResultNetworkDown&lt;br /&gt;
|-&lt;br /&gt;
| 0x1AE7B || 123 || 215 || ResultClientPkiAlreadyRegistered&lt;br /&gt;
|-&lt;br /&gt;
| 0x1B47B || 123 || 218 || ResultMaxServerPkiRegistered&lt;br /&gt;
|-&lt;br /&gt;
| 0x25A7B || 123 || 301 || ResultSslErrorInvalidCertDomain&lt;br /&gt;
|-&lt;br /&gt;
| 0x25C7B || 123 || 302 || ResultSslErrorNoCertificate&lt;br /&gt;
|-&lt;br /&gt;
| 0x25E7B || 123 || 303 || ResultSslErrorExpiredCertificate&lt;br /&gt;
|-&lt;br /&gt;
| 0x2607B || 123 || 304 || ResultSslErrorRevokedCertificate&lt;br /&gt;
|-&lt;br /&gt;
| 0x2627B || 123 || 305 || ResultSslErrorUnsupportedCertificate&lt;br /&gt;
|-&lt;br /&gt;
| 0x2647B || 123 || 306 || ResultSslErrorUnknownCertificate&lt;br /&gt;
|-&lt;br /&gt;
| 0x2667B || 123 || 307 || ResultSslErrorBadCertificate&lt;br /&gt;
|-&lt;br /&gt;
| 0x2687B || 123 || 308 || ResultSslErrorUnkownCa&lt;br /&gt;
|-&lt;br /&gt;
| 0x26A7B || 123 || 309 || ResultSslErrorAccessDenied&lt;br /&gt;
|-&lt;br /&gt;
| 0x26C7B || 123 || 310 || ResultSslErrorReceivedUnkownData&lt;br /&gt;
|-&lt;br /&gt;
| 0x26E7B || 123 || 311 || ResultSslErrorReceivedMalformedData&lt;br /&gt;
|-&lt;br /&gt;
| 0x2707B || 123 || 312 || ResultSslErrorReceivedUnexpectedHandshakeData&lt;br /&gt;
|-&lt;br /&gt;
| 0x2727B || 123 || 313 || ResultSslErrorReceivedUnexpectedRecordData&lt;br /&gt;
|-&lt;br /&gt;
| 0x2747B || 123 || 314 || ResultSslErrorReceivedTooLongRecord&lt;br /&gt;
|-&lt;br /&gt;
| 0x2767B || 123 || 315 || ResultSslErrorUnexpectedHelloVerifyRequest&lt;br /&gt;
|-&lt;br /&gt;
| 0x2787B || 123 || 316 || ResultSslErrorUnexpectedCertificateStatusResponse&lt;br /&gt;
|-&lt;br /&gt;
| 0x27A7B || 123 || 317 || ResultSslErrorInconsistentSignAlgorithm&lt;br /&gt;
|-&lt;br /&gt;
| 0x27C7B || 123 || 318 || ResultSslErrorInsufficientSecurity&lt;br /&gt;
|-&lt;br /&gt;
| 0x27E7B || 123 || 319 || ResultSslErrorDecryptionWithInvalidMac&lt;br /&gt;
|-&lt;br /&gt;
| 0x2827B || 123 || 321 || ResultSslErrorDigestCalculationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x2847B || 123 || 322 || ResultSslErrorMacCalculationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x2887B || 123 || 324 || ResultSslErrorNoExtendedField&lt;br /&gt;
|-&lt;br /&gt;
| 0x28A7B || 123 || 325 || ResultSslErrorUntrustedOid&lt;br /&gt;
|-&lt;br /&gt;
| 0x28C7B || 123 || 326 || ResultSslErrorInvalidPolicy&lt;br /&gt;
|-&lt;br /&gt;
| 0x2947B || 123 || 330 || ResultSslErrorDecompressionFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0xBBA7B || 123 || 1501 || ResultSslAlertCloseNotify&lt;br /&gt;
|-&lt;br /&gt;
| 0xBBC7B || 123 || 1502 || ResultSslAlertUnexpectedMessage&lt;br /&gt;
|-&lt;br /&gt;
| 0xBBE7B || 123 || 1503 || ResultSslAlertBadRecordMac&lt;br /&gt;
|-&lt;br /&gt;
| 0xBC07B || 123 || 1504 || ResultSslAlertDecriptionFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0xBC27B || 123 || 1505 || ResultSslAlertRecordOverfrlow&lt;br /&gt;
|-&lt;br /&gt;
| 0xBC47B || 123 || 1506 || ResultSslAlertDecompressionFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0xBC67B || 123 || 1507 || ResultSslAlertHandshakeFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0xBCA7B || 123 || 1509 || ResultSslAlertBadCertificate&lt;br /&gt;
|-&lt;br /&gt;
| 0xBCC7B || 123 || 1510 || ResultSslAlertUnsupportedCertificate&lt;br /&gt;
|-&lt;br /&gt;
| 0xBCE7B || 123 || 1511 || ResultSslAlertCertificateRevoked&lt;br /&gt;
|-&lt;br /&gt;
| 0xBD07B || 123 || 1512 || ResultSslAlertCertificateExpired&lt;br /&gt;
|-&lt;br /&gt;
| 0xBD27B || 123 || 1513 || ResultSslAlertCertificateUnkown&lt;br /&gt;
|-&lt;br /&gt;
| 0xBD47B || 123 || 1514 || ResultSslAlertIllegalParameter&lt;br /&gt;
|-&lt;br /&gt;
| 0xBD67B || 123 || 1515 || ResultSslAlertUnknownCa&lt;br /&gt;
|-&lt;br /&gt;
| 0xBD87B || 123 || 1516 || ResultSslAlertAccessDenied&lt;br /&gt;
|-&lt;br /&gt;
| 0xBDA7B || 123 || 1517 || ResultSslAlertDecodeError&lt;br /&gt;
|-&lt;br /&gt;
| 0xBDC7B || 123 || 1518 || ResultSslAlertDecryptError&lt;br /&gt;
|-&lt;br /&gt;
| 0xBDE7B || 123 || 1519 || ResultSslAlertExportRestriction&lt;br /&gt;
|-&lt;br /&gt;
| 0xBE07B || 123 || 1520 || ResultSslAlertProtocolVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0xBE27B || 123 || 1521 || ResultSslAlertInsufficientSecurity&lt;br /&gt;
|-&lt;br /&gt;
| 0xBE47B || 123 || 1522 || ResultSslAlertInternalError&lt;br /&gt;
|-&lt;br /&gt;
| 0xBE67B || 123 || 1523 || ResultSslAlertInappropriateFallback&lt;br /&gt;
|-&lt;br /&gt;
| 0xBE87B || 123 || 1524 || ResultSslAlertUserCancelled&lt;br /&gt;
|-&lt;br /&gt;
| 0xBEA7B || 123 || 1525 || ResultSslAlertNoRenegotiation&lt;br /&gt;
|-&lt;br /&gt;
| 0xBEC7B || 123 || 1526 || ResultSslAlertUnsupportedExtention&lt;br /&gt;
|-&lt;br /&gt;
| 0xBEE7B || 123 || 1527 || ResultSslAlertCertificateUnobtainable&lt;br /&gt;
|-&lt;br /&gt;
| 0xBF07B || 123 || 1528 || ResultSslAlertUnrecognizedName&lt;br /&gt;
|-&lt;br /&gt;
| 0xBF27B || 123 || 1529 || ResultSslAlertBadCertificateStatusResponse&lt;br /&gt;
|-&lt;br /&gt;
| 0xBF47B || 123 || 1530 || ResultSslAlertBadCertificateHashValue&lt;br /&gt;
|-&lt;br /&gt;
| 0x27127B || 123 || 5001 || Converted from [https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/SSL_functions/sslerr.html NSS] SSL error -12155 (SSL_ERROR_RX_SHORT_DTLS_READ).&lt;br /&gt;
|-&lt;br /&gt;
| 0x271E7B || 123 || 5007 || Out-of-bounds error during error conversion.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7C || 124 || 0 || ResultCancelled&lt;br /&gt;
|-&lt;br /&gt;
| 0x27C || 124 || 1 || ResultCancelledByUser&lt;br /&gt;
|-&lt;br /&gt;
| 0x287C || 124 || 20 || ResultInvalidUserId&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A7C || 124 || 21 || ResultInvalidUserPosition&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C7C || 124 || 22 || ResultInvalidApplication&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C7C || 124 || 30 || ResultNullptr&lt;br /&gt;
|-&lt;br /&gt;
| 0x3E7C || 124 || 31 || ResultInsufficientBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0x407C || 124 || 32 || ResultInvalidArrayLength&lt;br /&gt;
|-&lt;br /&gt;
| 0x427C || 124 || 33 || ResultInvalidStringFormat&lt;br /&gt;
|-&lt;br /&gt;
| 0x447C || 124 || 34 || ResultValueOutOfRange&lt;br /&gt;
|-&lt;br /&gt;
| 0x507C || 124 || 40 || ResultInvalidObjectAccess&lt;br /&gt;
|-&lt;br /&gt;
| 0x527C || 124 || 41 || ResultInvalidProtocolAccess&lt;br /&gt;
|-&lt;br /&gt;
| 0x767C || 124 || 59 || ResultInternetConnectionRequestNotAccepted&lt;br /&gt;
|-&lt;br /&gt;
| 0xC87C || 124 || 100 || ResultUserNotExist&lt;br /&gt;
|-&lt;br /&gt;
| 0xCA7C || 124 || 101 || ResultUserAlreadyOpened&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC7C || 124 || 102 || ResultUserAlreadyClosed&lt;br /&gt;
|-&lt;br /&gt;
| 0xCE7C || 124 || 103 || ResultUserReferred&lt;br /&gt;
|-&lt;br /&gt;
| 0xD07C || 124 || 104 || ResultUserUnqualified&lt;br /&gt;
|-&lt;br /&gt;
| 0xD27C || 124 || 105 || ResultNeverBeenQualified&lt;br /&gt;
|-&lt;br /&gt;
| 0x1907C || 124 || 200 || ResultNetworkServiceAccountRegistrationRequired&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A47C || 124 || 210 || ResultNetworkServiceAccountCredentialBroken&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A67C || 124 || 211 || ResultNetworkServiceAccountUnmanaged&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A87C || 124 || 212 || ResultNetworkServiceAccountBanned&lt;br /&gt;
|-&lt;br /&gt;
| 0x1CC7C || 124 || 230 || ResultNintendoAccountLinkageBroken&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E07C || 124 || 240 || ResultNintendoAccountStateOtherButInteractionRequired&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E27C || 124 || 241 || ResultNintendoAccountStateDeleted&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E47C || 124 || 242 || ResultNintendoAccountStateBanned&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E67C || 124 || 243 || ResultNintendoAccountStateSuspended&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E87C || 124 || 244 || ResultNintendoAccountStateWithdrawn&lt;br /&gt;
|-&lt;br /&gt;
| 0x1EA7C || 124 || 245 || ResultNintendoAccountStateTermsAgreementRequired&lt;br /&gt;
|-&lt;br /&gt;
| 0x2067C || 124 || 259 || ResultNintendoAccountStateReauthorizationRequired&lt;br /&gt;
|-&lt;br /&gt;
| 0x17707C || 124 || 3000 || ResultUnacceptableSystemVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0x17727C || 124 || 3001 || ResultUnacceptableApplicationVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F4E7C || 124 || 4007 || [https://en-americas-support.nintendo.com/app/answers/detail/a_id/28046/ Account Permanent Ban]&lt;br /&gt;
|-&lt;br /&gt;
| 0x23387C || 124 || 4508 || [https://en-americas-support.nintendo.com/app/answers/detail/a_id/28046/ Account Permanent Ban]&lt;br /&gt;
|-&lt;br /&gt;
| 0x234A7C || 124 || 4517 || [https://en-americas-support.nintendo.com/app/answers/detail/a_id/43652/ Account Ban]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24027C || 124 || 4609 || [https://en-americas-support.nintendo.com/app/answers/detail/a_id/46482/ Service Discontinued]&lt;br /&gt;
|-&lt;br /&gt;
| 0x27107C || 124 || 5000 || ResultInvalidParams&lt;br /&gt;
|-&lt;br /&gt;
| 0x27127C || 124 || 5001 || ResultInvalidRequest&lt;br /&gt;
|-&lt;br /&gt;
| 0x27147C || 124 || 5002 || ResultInvalidDeviceAccount&lt;br /&gt;
|-&lt;br /&gt;
| 0x27167C || 124 || 5003 || ResultInvalidNdasAppAuthnToken&lt;br /&gt;
|-&lt;br /&gt;
| 0x27187C || 124 || 5004 || ResultInvalidIdp&lt;br /&gt;
|-&lt;br /&gt;
| 0x271A7C || 124 || 5005 || ResultInvalidIdpAccount&lt;br /&gt;
|-&lt;br /&gt;
| 0x271C7C || 124 || 5006 || ResultLinkedUserNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x271E7C || 124 || 5007 || ResultInvalidFriendCodeFormat&lt;br /&gt;
|-&lt;br /&gt;
| 0x27207C || 124 || 5008 || ResultUserLinkNotExist&lt;br /&gt;
|-&lt;br /&gt;
| 0x27D87C || 124 || 5100 || ResultInvalidRawContent&lt;br /&gt;
|-&lt;br /&gt;
| 0x27DA7C || 124 || 5101 || ResultInsufficientScope&lt;br /&gt;
|-&lt;br /&gt;
| 0x27DC7C || 124 || 5102 || ResultForbidden&lt;br /&gt;
|-&lt;br /&gt;
| 0x27DE7C || 124 || 5103 || ResultUnavailableDeviceAccount&lt;br /&gt;
|-&lt;br /&gt;
| 0x27E07C || 124 || 5104 || ResultResourceIsNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x27E27C || 124 || 5105 || ResultMethodNotAllowed&lt;br /&gt;
|-&lt;br /&gt;
| 0x27E47C || 124 || 5106 || ResultNotAcceptableLanguage&lt;br /&gt;
|-&lt;br /&gt;
| 0x27E67C || 124 || 5107 || ResultResourceAlreadyExists&lt;br /&gt;
|-&lt;br /&gt;
| 0x27E87C || 124 || 5108 || ResultUserLinkAlreadyExists&lt;br /&gt;
|-&lt;br /&gt;
| 0x27EA7C || 124 || 5109 || ResultPreconditionFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x27EC7C || 124 || 5110 || ResultFriendCodeUnregenerableState&lt;br /&gt;
|-&lt;br /&gt;
| 0x27EE7C || 124 || 5111 || ResultBannedUser&lt;br /&gt;
|-&lt;br /&gt;
| 0x27F07C || 124 || 5112 || ResultDeletedUser&lt;br /&gt;
|-&lt;br /&gt;
| 0x27F27C || 124 || 5113 || ResultMembershipRequired&lt;br /&gt;
|-&lt;br /&gt;
| 0x27F47C || 124 || 5114 || ResultBannedUserByApplication&lt;br /&gt;
|-&lt;br /&gt;
| 0x28A07C || 124 || 5200 || ResultInternalServerError&lt;br /&gt;
|-&lt;br /&gt;
| 0x28B47C || 124 || 5210 || ResultCouldNotConfirmMembership&lt;br /&gt;
|-&lt;br /&gt;
| 0x29027C || 124 || 5249 || ResultUnderMaintenance&lt;br /&gt;
|-&lt;br /&gt;
| 0x27E || 126 || 1 || ResultInvalid&lt;br /&gt;
|-&lt;br /&gt;
| 0x87E || 126 || 4 || ResultNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0xCE7E || 126 || 67 || Invalid database signature value (should be &amp;quot;NFDB&amp;quot;).&lt;br /&gt;
|-&lt;br /&gt;
| 0xD27E || 126 || 69 || Invalid database entry count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1987E || 126 || 204 || ResultDevelopmentOnly&lt;br /&gt;
|-&lt;br /&gt;
| 0x627F || 127 || 49 || Invalid NFP backup data header / entry header size (entry count / UUID length).&lt;br /&gt;
|-&lt;br /&gt;
| 0x667F || 127 || 51 || Invalid NFP backup data header / entry header CRC32.&lt;br /&gt;
|-&lt;br /&gt;
| 0x807F || 127 || 64 || Device not found / no devices available.&lt;br /&gt;
|-&lt;br /&gt;
| 0x827F || 127 || 65 || Invalid argument.&lt;br /&gt;
|-&lt;br /&gt;
| 0x847F || 127 || 66 || Invalid amiibo UTF-8 name.&lt;br /&gt;
|-&lt;br /&gt;
| 0x867F || 127 || 67 || Invalid amiibo mii StoreData.&lt;br /&gt;
|-&lt;br /&gt;
| 0x887F || 127 || 68 || Too large application area size (&amp;gt; 0xD8 bytes).&lt;br /&gt;
|-&lt;br /&gt;
| 0x927F || 127 || 73 || Amiibo not mounted / not mounted in the required type.&lt;br /&gt;
|-&lt;br /&gt;
| 0xA07F || 127 || 80 || NFC not enabled in system settings.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC07F || 127 || 96 || Amiibo/session needs restart.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC27F || 127 || 97 || Invalid device state / entry not found in backup data.&lt;br /&gt;
|-&lt;br /&gt;
| 0xE27F || 127 || 113 || Internal FS error (failed to mount NFC savedata, invalid backup data file size).&lt;br /&gt;
|-&lt;br /&gt;
| 0xF07F || 127 || 120 || Invalid amiibo settings UTF-16 name / mii.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1007F || 127 || 128 || Amiibo application area does not exist / is not created.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1207F || 127 || 144 || Invalid amiibo data SHA256 hash / invalid amiibo header 0xA5 magic.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1307F || 127 || 152 || Amiibo application area access ID mismatch.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1507F || 127 || 168 || Amiibo application area already exists.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1647F || 127 || 178 || Malformed amiibo (invalid protocol / tag type / NTAG215 lock .fields / NTAG215 CFG)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1687F || 127 || 180 || Invalid amiibo tag SHA256 hash.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1707F || 127 || 184 || Invalid amiibo tag type.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1B07F || 127 || 216 || Internal FS error (NFC savedata busy / file already exists).&lt;br /&gt;
|-&lt;br /&gt;
| 0x480 || 128 || 2 || IStorage not available.&lt;br /&gt;
|-&lt;br /&gt;
| 0x680 || 128 || 3 || No messages.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4680 || 128 || 35 || Error while launching applet.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4A80 || 128 || 37 || Title-ID not found. Caused by code 0x410 when applet launch fails.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3E880 || 128 || 500 || Invalid input.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3EC80 || 128 || 502 || IStorage has already been opened by another accessor.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3EE80 || 128 || 503 || IStorage Read/Write out-of-bounds.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3F480 || 128 || 506 || Invalid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3FE80 || 128 || 511 || IStorage opened as wrong type (data opened as transfermem, transfermem opened as data).&lt;br /&gt;
|-&lt;br /&gt;
| 0x40080 || 128 || 512 || Unbalanced fatal section leave (returned when executing LeaveFatalSection without a preceding EnterFatalSection call).&lt;br /&gt;
|-&lt;br /&gt;
| 0x40C80 || 128 || 518 || Null object.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4B080 || 128 || 600 || Failed to allocate memory for IStorage.&lt;br /&gt;
|-&lt;br /&gt;
| 0x59080 || 128 || 712 || Thread stack pool exhausted (out of memory).&lt;br /&gt;
|-&lt;br /&gt;
| 0x79C80 || 128 || 974 || DebugMode not enabled.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7A880 || 128 || 980 || &amp;lt;code&amp;gt;am.debug!dev_function&amp;lt;/code&amp;gt; setting needs to be set / DebugMode not enabled.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7CC80 || 128 || 998 || Not implemented.&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC81 || 129 || 102 || Transmission not agreed.&lt;br /&gt;
|-&lt;br /&gt;
| 0xD281 || 129 || 105 || Network unavailable.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7DA81 || 129 || 1005 || HTTP error: Couldnt resolve proxy.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7DC81 || 129 || 1006 || HTTP error: Couldnt resolve host.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7DE81 || 129 || 1007 || HTTP error: Couldnt connect.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7FE81 || 129 || 1023 || HTTP error: Write error.&lt;br /&gt;
|-&lt;br /&gt;
| 0x80481 || 129 || 1026 || HTTP error: Read error.&lt;br /&gt;
|-&lt;br /&gt;
| 0x80681 || 129 || 1027 || HTTP error: Out of memory.&lt;br /&gt;
|-&lt;br /&gt;
| 0x80881 || 129 || 1028 || HTTP error: Operation timedout.&lt;br /&gt;
|-&lt;br /&gt;
| 0x81681 || 129 || 1035 || HTTP error: SSL connect error.&lt;br /&gt;
|-&lt;br /&gt;
| 0x83681 || 129 || 1051 || HTTP error: Peer failed verification.&lt;br /&gt;
|-&lt;br /&gt;
| 0x83881 || 129 || 1052 || HTTP error: Got nothing.&lt;br /&gt;
|-&lt;br /&gt;
| 0x83E81 || 129 || 1055 || HTTP error: Send error.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84081 || 129 || 1056 || HTTP error: Recv error.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84481 || 129 || 1058 || HTTP error: SSL cert problem.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84681 || 129 || 1059 || HTTP error: SSL cipher.&lt;br /&gt;
|-&lt;br /&gt;
| 0x84881 || 129 || 1060 || HTTP error: SSL CA cert.&lt;br /&gt;
|-&lt;br /&gt;
| 0x12C081 || 129 || 2400 || Server error: Status 400.&lt;br /&gt;
|-&lt;br /&gt;
| 0x12C281 || 129 || 2401 || Server error: Status 401.&lt;br /&gt;
|-&lt;br /&gt;
| 0x12C681 || 129 || 2403 || Server error: Status 403.&lt;br /&gt;
|-&lt;br /&gt;
| 0x138881 || 129 || 2500 || Server error: Status 500.&lt;br /&gt;
|-&lt;br /&gt;
| 0x138E81 || 129 || 2503 || Server error: Status 503.&lt;br /&gt;
|-&lt;br /&gt;
| 0x139081 || 129 || 2504 || Server error: Status 504.&lt;br /&gt;
|-&lt;br /&gt;
| 0xA83 || 131 || 5 || Unrecognized applet ID.&lt;br /&gt;
|-&lt;br /&gt;
| 0x485 || 133 || 2 || Invalid DVFS table ID.&lt;br /&gt;
|-&lt;br /&gt;
| 0x685 || 133 || 3 || DVFS table ID for debug only.&lt;br /&gt;
|-&lt;br /&gt;
| 0x885 || 133 || 4 || Invalid parameter.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1489 || 137 || 10 || Already initialized.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C89 || 137 || 30 || Task not found.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5089 || 137  || 40 || Memory allocation failed / bad input.&lt;br /&gt;
|-&lt;br /&gt;
| 0x29489 || 137 || 330 || [[NCM_services#ContentMetaType|ContentMetaType]] doesn&#039;t match SystemUpdate.&lt;br /&gt;
|-&lt;br /&gt;
| 0x271289 || 137 || 5001 || One of the following socket errors occurred: ENETDOWN, ECONNRESET, EHOSTDOWN, EHOSTUNREACH, or EPIPE. Also occurs when the received size doesn&#039;t match the expected size (recvfrom() ret with [[NIM_services#Contents_Delivery|meta_size]] data receiving).&lt;br /&gt;
|-&lt;br /&gt;
| 0x272489 || 137 || 5010 || Socket was [[Sockets_services|shutdown()]] due to the async operation being cancelled.&lt;br /&gt;
|-&lt;br /&gt;
| 0x273889 || 137 || 5020 || Too many internal output entries with [[NIM_services|nim]] cmd42, system is [[NIM_services#Contents_Delivery|Internet-connected]], or an unrecognized socket error occured.&lt;br /&gt;
|-&lt;br /&gt;
| 0x27D889 || 137 || 5100 || Connection timeout.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A4489 || 137 || 5410 || Invalid [[NIM_services#Contents_Delivery|ID]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A5889 || 137 || 5420 || Invalid [[NIM_services#Contents_Delivery|magicnum]]. Can also be caused by the connection being closed by the peer, since non-negative return values from recv() are ignored in this case.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A6C89 || 137 || 5430 || Invalid [[NIM_services#Contents_Delivery|data_size]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A8089 || 137 || 5440 || The input [[NCM_services#ContentMetaKey|ContentMetaKey]] doesn&#039;t match the ContentMetaKey in state.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A9489 || 137 || 5450 || Invalid [[NIM_services#Contents_Delivery|meta_size]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x36B289 || 137 || 7001 || HTTP invalid response code (&amp;gt;=600).&lt;br /&gt;
|-&lt;br /&gt;
| 0x36B489 || 137 || 7002 || HTTP invalid client response code (4xx).&lt;br /&gt;
|-&lt;br /&gt;
| 0x36B689 || 137 || 7003 || HTTP invalid server response code (5xx).&lt;br /&gt;
|-&lt;br /&gt;
| 0x36B889 || 137 || 7004 || HTTP invalid redirect response code (3xx).&lt;br /&gt;
|-&lt;br /&gt;
| 0x3CF089 || 137 || 7800 || Unknown/invalid libcurl error.&lt;br /&gt;
|-&lt;br /&gt;
| 0x68A || 138 || 3 || NotInitialized&lt;br /&gt;
|-&lt;br /&gt;
| 0x28C || 140 || 1 || ResultInterfaceInvalid&lt;br /&gt;
|-&lt;br /&gt;
| 0xA8C || 140 || 5 || ResultMemAllocFailure&lt;br /&gt;
|-&lt;br /&gt;
| 0x108C || 140 || 8 || ResultInternalStateError&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E8C || 140 || 15 || ResultEndpointStateInvalid&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A8C || 140 || 21 || ResultUrbLimitExceeded&lt;br /&gt;
|-&lt;br /&gt;
| 0x608C || 140 || 48 || ResultInvalidDeviceState&lt;br /&gt;
|-&lt;br /&gt;
| 0x628C || 140 || 49 || ResultUsbEndpointAlreadyOpen&lt;br /&gt;
|-&lt;br /&gt;
| 0x648C || 140 || 50 || ResultInvalidAlternateSetting&lt;br /&gt;
|-&lt;br /&gt;
| 0x668C || 140 || 51 || USB data-transfer in progress.&lt;br /&gt;
|-&lt;br /&gt;
| 0x868C || 140 || 67 || ResultPlatformInvalid&lt;br /&gt;
|-&lt;br /&gt;
| 0xC88C || 140 || 100 || ResultInvalidArgument&lt;br /&gt;
|-&lt;br /&gt;
| 0xCA8C || 140 || 101 || ResultInvalidOffset&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC8C || 140 || 102 || ResultInvalidSize&lt;br /&gt;
|-&lt;br /&gt;
| 0xCE8C || 140 || 103 || ResultInvalidAlignment&lt;br /&gt;
|-&lt;br /&gt;
| 0xD48C || 140 || 106 || Invalid descriptor.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1928C || 140 || 201 || ResultOperationDenied&lt;br /&gt;
|-&lt;br /&gt;
| 0x1BE8E || 142 || 223 || [[Network_Interface_services#IsAnyInternetRequestAccepted|IsAnyInternetRequestAccepted]] with the output from [[#Network_Interface_services#GetClientId|GetClientId]] returned false.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1928F || 143 || 201 || ResultFailureLowLayerGeneral&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F68F || 143 || 251 || ResultInternalErrorMultipleConnection&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F88F || 143 || 252 || ResultInternalErrorOverConnection&lt;br /&gt;
|-&lt;br /&gt;
| 0x1FA8F || 143 || 253 || ResultInternalErrorUnHandledCoreEvent&lt;br /&gt;
|-&lt;br /&gt;
| 0x1FC8F || 143 || 254 || ResultInternalErrorUnHandledHidEvent&lt;br /&gt;
|-&lt;br /&gt;
| 0x1FE8F || 143 || 255 || ResultInternalErrorUnHandledApiId&lt;br /&gt;
|-&lt;br /&gt;
| 0x2008F || 143 || 256 || ResultInternalErrorTimeOut&lt;br /&gt;
|-&lt;br /&gt;
| 0x2028F || 143 || 257 || ResultInternalErrorQueueFull&lt;br /&gt;
|-&lt;br /&gt;
| 0x2048F || 143 || 258 || ResultInternalErrorInvalidTsi&lt;br /&gt;
|-&lt;br /&gt;
| 0x2068F || 143 || 259 || ResultInternalErrorInvalidUsecase&lt;br /&gt;
|-&lt;br /&gt;
| 0x2088F || 143 || 260 || ResultInternalErrorInvalidOperationOnSleep&lt;br /&gt;
|-&lt;br /&gt;
| 0x20A8F || 143 || 261 || ResultInternalErrorFaultyDesign&lt;br /&gt;
|-&lt;br /&gt;
| 0x20C8F || 143 || 262 || ResultInternalErrorTimeoutDisablePageScan&lt;br /&gt;
|-&lt;br /&gt;
| 0x20E8F || 143 || 263 || ResultInternalErrorTimeoutDisconnectAllDevices&lt;br /&gt;
|-&lt;br /&gt;
| 0x2108F || 143 || 264 || ResultInternalErrorTimeoutDisconnectDevice&lt;br /&gt;
|-&lt;br /&gt;
| 0x21A8F || 143 || 269 || ResultInternalErrorRecoveryPrecondition&lt;br /&gt;
|-&lt;br /&gt;
| 0x21E8F || 143 || 271 || ResultInternalErrorTimeoutWaitForLlrFinish&lt;br /&gt;
|-&lt;br /&gt;
| 0x2208F || 143 || 272 || ResultInternalErrorTimeoutBleConfigScanFilterCondition&lt;br /&gt;
|-&lt;br /&gt;
| 0x2228F || 143 || 273 || ResultInternalErrorTimeoutBleDisconnectAllDevices&lt;br /&gt;
|-&lt;br /&gt;
| 0x290 || 144 || 1 || Exited Abnormally ([[Applet_Manager_services#LibraryAppletExitReason|ExitReason]] == Abormal).&lt;br /&gt;
|-&lt;br /&gt;
| 0x690 || 144 || 3 || Canceled ([[Applet_Manager_services#LibraryAppletExitReason|ExitReason]] == Canceled).&lt;br /&gt;
|-&lt;br /&gt;
| 0x890 || 144 || 4 || Rejected.&lt;br /&gt;
|-&lt;br /&gt;
| 0xA90 || 144 || 5 || Exited Unexpectedly ([[Applet_Manager_services#LibraryAppletExitReason|ExitReason]] == Unexpected).&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A91 || 145 || 13 || [[Settings_services|DebugMode]] required.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3F4A91 || 145 || 8101 || NotImplemented&lt;br /&gt;
|-&lt;br /&gt;
| 0x293 || 147 || 1 || NotInitialized&lt;br /&gt;
|-&lt;br /&gt;
| 0x493 || 147 || 2 || AlreadyInitialized&lt;br /&gt;
|-&lt;br /&gt;
| 0x693 || 147 || 3 || OutOfArraySpace&lt;br /&gt;
|-&lt;br /&gt;
| 0x893 || 147 || 4 || OutOfFieldSpace&lt;br /&gt;
|-&lt;br /&gt;
| 0xA93 || 147 || 5 || OutOfMemory&lt;br /&gt;
|-&lt;br /&gt;
| 0xC93 || 147 || 6 || NotSupported&lt;br /&gt;
|-&lt;br /&gt;
| 0xE93 || 147 || 7 || InvalidArgument&lt;br /&gt;
|-&lt;br /&gt;
| 0x1093 || 147 || 8 || NotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x1293 || 147 || 9 || FieldCategoryMismatch&lt;br /&gt;
|-&lt;br /&gt;
| 0x1493 || 147 || 10 || FieldTypeMismatch&lt;br /&gt;
|-&lt;br /&gt;
| 0x1693 || 147 || 11 || AlreadyExists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1893 || 147 || 12 || CorruptJournal&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A93 || 147 || 13 || CategoryNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C93 || 147 || 14 || RequiredContextMissing&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E93 || 147 || 15 || RequiredFieldMissing&lt;br /&gt;
|-&lt;br /&gt;
| 0x2093 || 147 || 16 || FormatterError&lt;br /&gt;
|-&lt;br /&gt;
| 0x2293 || 147 || 17 || InvalidPowerState&lt;br /&gt;
|-&lt;br /&gt;
| 0x2493 || 147 || 18 || ArrayFieldTooLarge&lt;br /&gt;
|-&lt;br /&gt;
| 0x2693 || 147 || 19 || AlreadyOwned&lt;br /&gt;
|-&lt;br /&gt;
| 0x299 || 153 || 1 || ResultNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x499 || 153 || 2 || ResultOperationFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x699 || 153 || 3 || ResultInvalidSampleRate&lt;br /&gt;
|-&lt;br /&gt;
| 0x899 || 153 || 4 || ResultInsufficientBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0xA99 || 153 || 5 || ResultOutOfResource&lt;br /&gt;
|-&lt;br /&gt;
| 0xC99 || 153 || 6 || ResultDefaultAudioInNotAvailable&lt;br /&gt;
|-&lt;br /&gt;
| 0xE99 || 153 || 7 || ResultDefaultAudioOutNotAvailable&lt;br /&gt;
|-&lt;br /&gt;
| 0x1099 || 153 || 8 || Too many buffers are still unreleased.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1299 || 153 || 9 || ResultAlreadyOpen&lt;br /&gt;
|-&lt;br /&gt;
| 0x1499 || 153 || 10 || ResultInvalidChannelCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x5299 || 153 || 41 || ResultInvalidUpdateInfo&lt;br /&gt;
|-&lt;br /&gt;
| 0x5499 || 153 || 42 || ResultNoMemoryPoolEntry&lt;br /&gt;
|-&lt;br /&gt;
| 0x5699 || 153 || 42 || ResultCycleDetected&lt;br /&gt;
|-&lt;br /&gt;
| 0x28299 || 153 || 321 || ResultCodecSpeakerOverCurrent&lt;br /&gt;
|-&lt;br /&gt;
| 0x28499 || 153 || 322 || ResultCodecOverTemperature&lt;br /&gt;
|-&lt;br /&gt;
| 0x40099 || 153 || 512 || ResultNoAudioDeviceFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x40299 || 153 || 513 || ResultNotSupported&lt;br /&gt;
|-&lt;br /&gt;
| 0x40499 || 153 || 514 || ResultNotImplemented&lt;br /&gt;
|-&lt;br /&gt;
| 0x40699 || 153 || 515 || ResultInvalidSampleFormat&lt;br /&gt;
|-&lt;br /&gt;
| 0xC0099 || 153 || 1536 || Invalid handle.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC0899 || 153 || 1540 || [[Audio_services#Notes|ResultAudioDspAbort]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xC0C99 || 153 || 1542 || No mailbox response from the ADSP during ADSP initialization.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C9D || 157 || 30 || Address is NULL.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3E9D || 157 || 31 || PID is NULL.&lt;br /&gt;
|-&lt;br /&gt;
| 0x549D || 157 || 42 || Already bound.&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC9D || 157 || 102 || Invalid PID.&lt;br /&gt;
|-&lt;br /&gt;
| 0x49E || 158 || 2 || BootImagePackageNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x69E || 158 || 3 || InvalidBootImagePackage&lt;br /&gt;
|-&lt;br /&gt;
| 0x89E || 158 || 4 || TooSmallWorkBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0xA9E || 158 || 5 || NotAlignedWorkBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0xC9E || 158 || 6 || NeedsRepairBootImages&lt;br /&gt;
|-&lt;br /&gt;
| 0x29F || 159 || 1 || ResultCanceled&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A2 || 162 || 1 || ApplicationAborted&lt;br /&gt;
|-&lt;br /&gt;
| 0x4A2 || 162 || 2 || SystemModuleAborted&lt;br /&gt;
|-&lt;br /&gt;
| 0x6A2 || 162 || 3 || ApplicationExitTimeout&lt;br /&gt;
|-&lt;br /&gt;
| 0x8A2 || 162 || 4 || ForcedShutdownDetected&lt;br /&gt;
|-&lt;br /&gt;
| 0xC8A2 || 162 || 100 || UnacceptableApplicationVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0xCAA2 || 162 || 101 || UnacceptableAddOnContentVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0xAA3 || 163 || 5 || InRepairWithoutVolHeld&lt;br /&gt;
|-&lt;br /&gt;
| 0xCA3 || 163 || 6 || InRepairWithoutTimeReviserCartridge&lt;br /&gt;
|-&lt;br /&gt;
| 0x70A4 || 164 || 56 || ResultInternetRequestNotAccepted&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A5 || 165 || 1 || PmControl dispatched request timed out.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4A5 || 165 || 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x6A5 || 165 || 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x7D2A5 || 165 || 1001 || PmRequest aborted.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D2A5 || 165 || 1002 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xA8 || 168 || 0 || UndefinedInstruction&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A8 || 168 || 1 || InstructionAbort&lt;br /&gt;
|-&lt;br /&gt;
| 0x4A8 || 168 || 2 || DataAbort&lt;br /&gt;
|-&lt;br /&gt;
| 0x6A8 || 168 || 3 || AlignmentFault&lt;br /&gt;
|-&lt;br /&gt;
| 0x8A8 || 168 || 4 || DebuggerAttached&lt;br /&gt;
|-&lt;br /&gt;
| 0xAA8 || 168 || 5 || BreakPoint&lt;br /&gt;
|-&lt;br /&gt;
| 0xCA8 || 168 || 6 || UserBreak&lt;br /&gt;
|-&lt;br /&gt;
| 0xEA8 || 168 || 7 || DebuggerBreak&lt;br /&gt;
|-&lt;br /&gt;
| 0x10A8 || 168 || 8 || UndefinedSystemCall&lt;br /&gt;
|-&lt;br /&gt;
| 0x12A8 || 168 || 9 || MemorySystemError&lt;br /&gt;
|-&lt;br /&gt;
| 0xC6A8 || 168 || 99 || IncompleteReport&lt;br /&gt;
|-&lt;br /&gt;
| 0x836AA || 170 || 1051 || Converted from Result 0x20F.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4AF || 175 || 2 || Bad version returned from calling the &amp;quot;nnjitpluginGetVersion&amp;quot; symbol.&lt;br /&gt;
|-&lt;br /&gt;
| 0xCAAF || 175 || 101 || Input NRO/NRR are too large for the storage buffer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4B0AF || 175 || 600 || Symbol funcptr used by this cmd is not initialized (Control/GenerateCode).&lt;br /&gt;
|-&lt;br /&gt;
| 0x4B2AF || 175 || 601 || DllPlugin Not initialized, or plugin NRO has already been loaded.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4B4AF || 175 || 602 || An error was returned from calling the symbol funcptr with the Control cmd.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC8B2 || 178 || 100 || Invalid user ID.&lt;br /&gt;
|-&lt;br /&gt;
| 0xCAB2 || 178 || 101 || User does not exist.&lt;br /&gt;
|-&lt;br /&gt;
| 0x12CB2 || 178 || 150 || Service unavailable.&lt;br /&gt;
|-&lt;br /&gt;
| 0x190B2 || 178 || 200 || File storage failure.&lt;br /&gt;
|-&lt;br /&gt;
| 0xAB4 || 180 || 5 || Invalid event ID.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D0B5 || 181 || 1000 || Invalid ELicense ID.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F4EB5 || 181 || 4007 || Device authentication error: System update required.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F50B5 || 181 || 4008 || Device authentication error: [https://en-americas-support.nintendo.com/app/answers/detail/a_id/42061/ Permanant Ban].&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F52B5 || 181 || 4009 || Device authentication error: Internal server error.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F54B5 || 181 || 4010 || Device authentication error: Under maintenance.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F62B5 || 181 || 4017 || Device authentication error: [https://en-americas-support.nintendo.com/app/answers/detail/a_id/43653/ Ban].&lt;br /&gt;
|-&lt;br /&gt;
| 0x58ACA || 202 || 709 || Npad ID is out of range.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2032CA || 202 || 4121 || [[Settings_services#ButtonConfigSettings|ButtonConfigSettings]] IsFull flag is clear.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28CB || 203 || 20 || The [6.0.0+] Authentication challenge failed.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2CCB || 203 || 22 || Converted from [[Shared_Database_services|pl]] Result 0x7D2AA during [[LDN_services|Initialize]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x34CB || 203 || 26 || Converted from [[Shared_Database_services|pl]] Result 0x7D6AA during [[LDN_services|Initialize]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x38CB || 203 || 28 || Converted from [[Shared_Database_services|pl]] Result range 0x7D0AA - 0x832AA during [[LDN_services|Initialize]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x3ACB || 203 || 29 || Invalid [[LDN_services#Protocol|Protocol]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x4ACB || 203 || 37 || [[LDN_services#State|State]] is not Initialized.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4ECB || 203 || 39 || Invalid [[LDN_services#State|State]] or state field.&lt;br /&gt;
|-&lt;br /&gt;
| 0x52CB || 203 || 41 || Converted from [[Shared_Database_services|pl]] Result 0x836AA during [[LDN_services|Initialize]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x82CB || 203 || 65 || ResultNetworkNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x84CB || 203 || 66 || ResultConnectionTimeout&lt;br /&gt;
|-&lt;br /&gt;
| 0x86CB || 203 || 67 || ResultConnectionRejected&lt;br /&gt;
|-&lt;br /&gt;
| 0xC0CB || 203 || 96 || Invalid input or state.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC2CB || 203 || 97 || Matching LocalCommunicationId not found in the user-process [[NACP_Format|control.nacp]].&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2CB || 203 || 113 || ResultLowerVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4CB || 203 || 114 || ResultHigherVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0CD || 205 || 120 || IrsensorNotReady&lt;br /&gt;
|-&lt;br /&gt;
| 0x198CD || 205 || 204 || IR camera invalid handle value.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A8CD || 205 || 212 || IR camera handle pointer is null.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6CE || 206 || 3 || AlbumWorkMemoryError&lt;br /&gt;
|-&lt;br /&gt;
| 0x10CE || 206 || 8 || AlbumOutOfRange&lt;br /&gt;
|-&lt;br /&gt;
| 0x18CE || 206 || 12 || AlbumInvalidTimestamp&lt;br /&gt;
|-&lt;br /&gt;
| 0x1ACE || 206 || 13 || AlbumInvalidStorage&lt;br /&gt;
|-&lt;br /&gt;
| 0x1CCE || 206 || 14 || AlbumInvalidFileContents&lt;br /&gt;
|-&lt;br /&gt;
| 0x2ACE || 206 || 21 || AlbumIsNotMounted&lt;br /&gt;
|-&lt;br /&gt;
| 0x2CCE || 206 || 23 || AlbumFileNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0x30CE || 206 || 24 || AlbumInvalidFileData&lt;br /&gt;
|-&lt;br /&gt;
| 0x3CCE || 206 || 30 || AlbumReadBufferShortage&lt;br /&gt;
|-&lt;br /&gt;
| 0xAF2CE || 206 || 1401 || InternalAlbumLimitationFileCountLimit&lt;br /&gt;
|-&lt;br /&gt;
| 0x960D8 || 216 || 1200 || &amp;quot;This is not the Nintendo Account that you were using before the system transfer process was interrupted.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x962D8 || 216 || 1201 || &amp;quot;Save data cannot be transferred because there are too many save files.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x964D8 || 216 || 1202 || &amp;quot;Data cannot be transferred because there is not enough free space on the target console.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x966D8 || 216 || 1203 || &amp;quot;Unable to connect to the Internet.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x96AD8 || 216 || 1205 || &amp;quot;Can&#039;t download server data to this system.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0xFA4D8 || 216 || 2002 || &amp;quot;This is not the console you were communicating with before the system transfer process was interrupted.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x2710D8 || 216 || 5000 || &amp;quot;Unable to communicate with the other console.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x2714D8 || 216 || 5002 || &amp;quot;The connection to the other console was lost.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DA4D8 || 216 || 7890 || &amp;quot;A communication error has occurred. {...} The online service you attempted to use has ended.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DB6D8 || 216 || 7899 || &amp;quot;A server communication error has occurred.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DCED8 || 216 || 7911 || &amp;quot;There was a problem with the connection to the server.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DF6D8 || 216 || 7931 || &amp;quot;There was a problem with the connection to the server.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x3DF8D8 || 216 || 7932 || &amp;quot;There was a problem with the connection to the server.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x3E08D8 || 216 || 7940 || &amp;quot;There was a problem with the connection to the server.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x4652D8 || 216 || 9001 || &amp;quot;There was a problem with the connection to the server.&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x4DA || 218 || 2 || StatusManager entry IsValid flag not set, or controller-update currently in-progress.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6DA || 218 || 3 || Controller-update failed via the LibraryApplet.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8DA || 218 || 4 || Invalid BusHandle.&lt;br /&gt;
|-&lt;br /&gt;
| 0xADA || 218 || 5 || StatusManager entry flag +0x0 not set, or device not connected.&lt;br /&gt;
|-&lt;br /&gt;
| 0xEDA || 218 || 7 || PollingReceivedData not available.&lt;br /&gt;
|-&lt;br /&gt;
| 0x10DA || 218 || 8 || StatusManager entry DeviceEnabled flag not set, or flag +0x0 not set.&lt;br /&gt;
|-&lt;br /&gt;
| 0x12DA || 218 || 9 || ExternalDeviceId mismatch.&lt;br /&gt;
|-&lt;br /&gt;
| 0x14DA || 218 || 10 || BusHandle already initialized.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E4 || 228 || 1 || NotImplemented&lt;br /&gt;
|-&lt;br /&gt;
| 0x4E4 || 228 || 2 || NotAvailable&lt;br /&gt;
|-&lt;br /&gt;
| 0x6E4 || 228 || 3 || ApplicationNotRunning&lt;br /&gt;
|-&lt;br /&gt;
| 0x8E4 || 228 || 4 || BufferNotEnough&lt;br /&gt;
|-&lt;br /&gt;
| 0xAE4 || 228 || 5 || ApplicationContentNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0xCE4 || 228 || 6 || ContentMetaNotFound&lt;br /&gt;
|-&lt;br /&gt;
| 0xEE4 || 228 || 7 || OutOfMemory&lt;br /&gt;
|-&lt;br /&gt;
| 0x104E7 || 231 || 130 || Nullptr passed to the LocalCommunicationId [[NACP_Format|control.nacp]] validation func.&lt;br /&gt;
|-&lt;br /&gt;
| 0x140E7 || 231 || 160 || GroupInfo field out of range.&lt;br /&gt;
|-&lt;br /&gt;
| 0x142E7 || 231 || 161 || SupportedPlatform not appropriate for this operation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x146E7 || 231 || 163 || Invalid ServiceName.&lt;br /&gt;
|-&lt;br /&gt;
| 0x148E7 || 231 || 164 || Must provide PresharedBinaryKey.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C0E7 || 231 || 224 || Requested Priority value not allowed.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C2E7 || 231 || 225 || Matching LocalCommunicationId not found in the user-process [[NACP_Format|control.nacp]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x200E7 || 231 || 256 || Invalid flag.&lt;br /&gt;
|-&lt;br /&gt;
| 0x204E7 || 231 || 258 || Invalid SupportedPlatform.&lt;br /&gt;
|-&lt;br /&gt;
| 0x208E7 || 231 || 260 || Invalid StaticAesKeyIndex.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20AE7 || 231 || 261 || MemberCountMax cannot be greater than 8.&lt;br /&gt;
|-&lt;br /&gt;
| 0x210E7 || 231 || 264 || GroupInfo+8F must be 0x20.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Error Ranges ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Module || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
| 0xFA002-0x138602 || 2 || 2000-2499 || ResultSdCardAccessFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x136802-0x176E02 || 2 || 2500-2999 || ResultGameCardAccessFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x190002-0x1B5602 || 2 || 3200-3499 || ResultAllocationMemoryFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x1B5802-0x1F3E02 || 2 || 3500-3999 || ResultMmcAccessFailed&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F4002-0x270E02 || 2 || 4000-4999 || ResultDataCorrupted&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F4202-0x219602 || 2 || 4001-4299 || RomCorrupted&lt;br /&gt;
|-&lt;br /&gt;
| 0x219A02-0x232602 || 2 || 4301-4499 || SaveDataCorrupted&lt;br /&gt;
|-&lt;br /&gt;
| 0x232A02-0x23EE02 || 2 || 4501-4599 || NcaCorrupted&lt;br /&gt;
|-&lt;br /&gt;
| 0x23F202-0x243E02 || 2 || 4601-4639 || IntegrityVerificationStorageCorrupted&lt;br /&gt;
|-&lt;br /&gt;
| 0x244202-0x246602 || 2 || 4641-4659 || PartitionFileSystemCorrupted&lt;br /&gt;
|-&lt;br /&gt;
| 0x246A02-0x248E02 || 2 || 4661-4679 || BuiltInStorageCorrupted&lt;br /&gt;
|-&lt;br /&gt;
| 0x249202-0x24B602 || 2 || 4681-4699 || FatFileSystemCorrupted&lt;br /&gt;
|-&lt;br /&gt;
| 0x24BA02-0x24DE02 || 2 || 4701-4719 || ResultHostFileSystemCorrupted&lt;br /&gt;
|-&lt;br /&gt;
| 0x271002-0x2EDE02 || 2 || 5000-5999 || ResultUnexpected&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EE002-0x32C602 || 2 || 6000-6499 || ResultPreconditionViolation&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EE202-0x306E02 || 2 || 6001-6199 || ResultInvalidArgument&lt;br /&gt;
|-&lt;br /&gt;
| 0x2EE402-0x2F1A02 || 2 || 6002-6029 || ResultInvalidPath&lt;br /&gt;
|-&lt;br /&gt;
| 0x307002-0x313602 || 2 || 6200-6299 || ResultInvalidOperationForOpenMode&lt;br /&gt;
|-&lt;br /&gt;
| 0x313802-0x31FE02 || 2 || 6300-6399 || ResultUnsupportedOperation&lt;br /&gt;
|-&lt;br /&gt;
| 0x320002-0x326202 || 2 || 6400-6449 || ResultPermissionDenied&lt;br /&gt;
|-&lt;br /&gt;
| 0x390889-0x391889 || 137 || 7300-7308 || HTTP response code 300-308.&lt;br /&gt;
|-&lt;br /&gt;
| 0x39D089-0x39F289 || 137 || 7400-7417 || HTTP response code 400-417.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A9889-0x3AAA89 || 137 || 7500-7509 || HTTP response code 500-509.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3E8289-0x3F4089 || 137 || 8001-8096 || libcurl error 1-96.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Support Errors =&lt;br /&gt;
This section is for Support Errors displayed by the error-applet, separate from the normal Result Errors.&lt;br /&gt;
&lt;br /&gt;
== Modules ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 520 || Nverpt&lt;br /&gt;
|-&lt;br /&gt;
| 521 || Am_StuckMonitor&lt;br /&gt;
|-&lt;br /&gt;
| 600 || &lt;br /&gt;
|-&lt;br /&gt;
| 601 || &lt;br /&gt;
|-&lt;br /&gt;
| 602 || &lt;br /&gt;
|-&lt;br /&gt;
| 603 || &lt;br /&gt;
|-&lt;br /&gt;
| 604 || &lt;br /&gt;
|-&lt;br /&gt;
| 605 || &lt;br /&gt;
|-&lt;br /&gt;
| 606 || &lt;br /&gt;
|-&lt;br /&gt;
| 607 || &lt;br /&gt;
|-&lt;br /&gt;
| 608 || &lt;br /&gt;
|-&lt;br /&gt;
| 609 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 611 || &lt;br /&gt;
|-&lt;br /&gt;
| 612 || &lt;br /&gt;
|-&lt;br /&gt;
| 613 || &lt;br /&gt;
|-&lt;br /&gt;
| 614 || &lt;br /&gt;
|-&lt;br /&gt;
| 615 || &lt;br /&gt;
|-&lt;br /&gt;
| 616 || &lt;br /&gt;
|-&lt;br /&gt;
| 617 || &lt;br /&gt;
|-&lt;br /&gt;
| 618 || Pia&lt;br /&gt;
|-&lt;br /&gt;
| 619 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 621 || &lt;br /&gt;
|-&lt;br /&gt;
| 622 || &lt;br /&gt;
|-&lt;br /&gt;
| 623 || Eagle&lt;br /&gt;
|-&lt;br /&gt;
| 800 || [[Internet_Browser|LibAppletWeb]]&lt;br /&gt;
|-&lt;br /&gt;
| 801 || &lt;br /&gt;
|-&lt;br /&gt;
| 802 || &lt;br /&gt;
|-&lt;br /&gt;
| 803 || &lt;br /&gt;
|-&lt;br /&gt;
| 804 || &lt;br /&gt;
|-&lt;br /&gt;
| 805 || &lt;br /&gt;
|-&lt;br /&gt;
| 806 || &lt;br /&gt;
|-&lt;br /&gt;
| 807 || &lt;br /&gt;
|-&lt;br /&gt;
| 808 || &lt;br /&gt;
|-&lt;br /&gt;
| 809 || [[Internet_Browser|LibAppletAuth]]&lt;br /&gt;
|-&lt;br /&gt;
| 810 || [[Internet_Browser|LibAppletLns]]&lt;br /&gt;
|-&lt;br /&gt;
| 811 || [[Internet_Browser|LibAppletShop]]&lt;br /&gt;
|-&lt;br /&gt;
| 812 || &lt;br /&gt;
|-&lt;br /&gt;
| 813 || &lt;br /&gt;
|-&lt;br /&gt;
| 814 || &lt;br /&gt;
|-&lt;br /&gt;
| 815 || Coral&lt;br /&gt;
|-&lt;br /&gt;
| 816 || &lt;br /&gt;
|-&lt;br /&gt;
| 817 || &lt;br /&gt;
|-&lt;br /&gt;
| 818 || &lt;br /&gt;
|-&lt;br /&gt;
| 819 || &lt;br /&gt;
|-&lt;br /&gt;
| 820 || &lt;br /&gt;
|-&lt;br /&gt;
| 821 || &lt;br /&gt;
|-&lt;br /&gt;
| 899 ||&lt;br /&gt;
|-&lt;br /&gt;
| 999 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Error Codes ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Module || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
| Variable&lt;br /&gt;
| {web-applets listed above}&lt;br /&gt;
| 2750&lt;br /&gt;
| MP4 parsing failed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Homebrew Errors =&lt;br /&gt;
Custom errors used by homebrew libraries and applications.&lt;br /&gt;
&lt;br /&gt;
== Modules ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 345 || libnx&lt;br /&gt;
|-&lt;br /&gt;
| 346 || [[Homebrew ABI]]&lt;br /&gt;
|-&lt;br /&gt;
| 347 || Homebrew Loader&lt;br /&gt;
|-&lt;br /&gt;
| 348 || libnx NVIDIA errors&lt;br /&gt;
|-&lt;br /&gt;
| 349 || libnx Binder errors&lt;br /&gt;
|-&lt;br /&gt;
| 359 || deko3d&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Error Codes ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Module || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
| 0x35B || 347 || 1 || Failed to init SM.&lt;br /&gt;
|-&lt;br /&gt;
| 0x55B || 347 || 2 || Failed to init FS.&lt;br /&gt;
|-&lt;br /&gt;
| 0x75B || 347 || 3 || Failed to open NRO file. May also happen when SD card isn&#039;t inserted / SD mounting failed earlier.&lt;br /&gt;
|-&lt;br /&gt;
| 0x95B || 347 || 4 || Failed to read NRO header.&lt;br /&gt;
|-&lt;br /&gt;
| 0xB5B || 347 || 5 || Invalid NRO magic.&lt;br /&gt;
|-&lt;br /&gt;
| 0xD5B || 347 || 6 || Invalid NRO segments.&lt;br /&gt;
|-&lt;br /&gt;
| 0xF5B || 347 || 7 || Failed to read NRO.&lt;br /&gt;
|-&lt;br /&gt;
| 0x135B || 347 || 9 || Failed to allocate heap.&lt;br /&gt;
|-&lt;br /&gt;
| 0x255B || 347 || 18 || Failed to map code-binary memory.&lt;br /&gt;
|-&lt;br /&gt;
| 0x275B || 347 || 19 || Failed to map code memory (.text).&lt;br /&gt;
|-&lt;br /&gt;
| 0x295B || 347 || 20 || Failed to map code memory (.rodata).&lt;br /&gt;
|-&lt;br /&gt;
| 0x2B5B || 347 || 21 || Failed to map code memory (.data+.bss).&lt;br /&gt;
|-&lt;br /&gt;
| 0x315B || 347 || 24 || Failed to unmap code memory (.text).&lt;br /&gt;
|-&lt;br /&gt;
| 0x335B || 347 || 25 || Failed to unmap code memory (.rodata).&lt;br /&gt;
|-&lt;br /&gt;
| 0x355B || 347 || 26 || Failed to unmap code memory (.data+.bss).&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14651</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14651"/>
		<updated>2026-05-01T17:23:50Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header, which besides the DataMessageId contains:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || s32, must not be negative.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14650</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14650"/>
		<updated>2026-05-01T16:11:34Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* PrepareTransferDisconnect */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;. This bool indicates whether the previously mentioned network request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14649</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14649"/>
		<updated>2026-05-01T16:08:49Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || [[#ProcessTransferAsync|ProcessTransferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the earlier message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== ProcessTransferAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Verifies that the [[#WaitConnectionAsync|connected]] state flag is set.&lt;br /&gt;
* Calls a vfunc. When ret is false, call another vfunc.&lt;br /&gt;
* Call the above vfunc again. If the ret is still false, return an error.&lt;br /&gt;
* When a state flag is not set, calls a func.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] above is true, just return 0.&lt;br /&gt;
** Calls the same func as [[#WaitConnectionAsync|WaitConnectionAsync]], which has a message-loop + socket-closing and cleanup.&lt;br /&gt;
** Calls the same func as [[#TransferNextAsync|TransferNextAsync]] for using the network request.&lt;br /&gt;
** Abort if a state flag is not set.&lt;br /&gt;
** Calls the network-creation func from [[#WaitConnectionAsync|WaitConnectionAsync]], with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
* Enters a loop.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Initializes stack data.&lt;br /&gt;
*** Calls a func. This receives [[#Suspend|Suspend]], [[#SynchronizeState|SynchronizeState]], or [[#PrepareTransfer|PrepareTransfer]] and sends the response. Besides handling Suspend afterwards, this also copies a field to output (this is the output s32 mentioned below).&lt;br /&gt;
*** Calls a vfunc. When ret is true, cleanup and return 0.&lt;br /&gt;
*** Receives [[#TransferNext|TransferNext]] and sends the response.&lt;br /&gt;
** Calls a vfunc. When ret is true, return 0.&lt;br /&gt;
** If the Result from the above func is within the fs range for ResultDataCorrupted, and the output s32 from the func is not negative:&lt;br /&gt;
*** When a state field is less than the above s32, set another state field to that s32.&lt;br /&gt;
*** Break from the loop.&lt;br /&gt;
** If the above func returned error, break from the loop.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
The server returns an error following handling Suspend.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14642</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14642"/>
		<updated>2026-05-01T02:25:40Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* PrepareTransferDisconnect */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14641</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14641"/>
		<updated>2026-04-30T23:32:51Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This uses network message [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This uses network message [[#RequestServerProfile|RequestServerProfile]].&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func for RequestServerProfile used above.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Uses network message [[#Data|DataMessageId]] 0x12.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This uses network message [[#Leave|Leave]]. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14640</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14640"/>
		<updated>2026-04-30T20:31:10Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* Data */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#SendClientProfile|SendClientProfile]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends [[#RequestServerProfile|RequestServerProfile]], then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SystemVersion (same form as [[#SendClientProfile|SendClientProfile]])&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data, in which case:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls the same func as [[#SendClientProfile|SendClientProfile]] with the above SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
* The u8 at +0x0 must match 0x1.&lt;br /&gt;
* The two u64s at +0xC once ORRed must be non-zero.&lt;br /&gt;
* The u32 at +0x11C must be 0x1-0x800.&lt;br /&gt;
* The u64 at +0x120 must match state.&lt;br /&gt;
* Copies data into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=22.1.0&amp;diff=14639</id>
		<title>22.1.0</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=22.1.0&amp;diff=14639"/>
		<updated>2026-04-30T17:50:26Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* migration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Switch 22.1.0 system update was released on April 7, 2026 (UTC). This Switch update was released for the following regions: ALL.&lt;br /&gt;
&lt;br /&gt;
Security flaws fixed: &amp;lt;fill this in manually&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Change-log==&lt;br /&gt;
[https://en-americas-support.nintendo.com/app/answers/detail/a_id/22525/kw/nintendo%20switch%20system%20update Official] ALL change-log:&lt;br /&gt;
*   General system stability improvements to enhance the user&#039;s experience.&lt;br /&gt;
&lt;br /&gt;
==System Titles==&lt;br /&gt;
* The following titles were updated:&lt;br /&gt;
** Sysmodules: es, sdb, migration.&lt;br /&gt;
** Applets: qlaunch.&lt;br /&gt;
&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* [[System_Version_Title|SystemVersion]]: All files updated.&lt;br /&gt;
&lt;br /&gt;
=== IPC Interface Changes ===&lt;br /&gt;
* Unknown Interface prev-version: 0x7100045360 [ID = 0xae8071f6]&lt;br /&gt;
* Unknown Interface cur-version: 0x7100045360 [ID = 0xae8071f6]&lt;br /&gt;
* Unknown Interface prev-version: 0x7100060510 [ID = 0xef2a5618]&lt;br /&gt;
* Unknown Interface cur-version: 0x7100060510 [ID = 0xef2a5618]&lt;br /&gt;
* Unknown Interface prev-version: 0x7100129570 [ID = 0x29d8801c]&lt;br /&gt;
* Unknown Interface cur-version: 0x7100129570 [ID = 0x29d8801c]&lt;br /&gt;
&lt;br /&gt;
=== [[ETicket_services|es]] ===&lt;br /&gt;
On [S1] the codebin is identical except for the BuildId. The actual changes are likely S2-only?&lt;br /&gt;
&lt;br /&gt;
=== [[Shared_Database_services|sdb]] ===&lt;br /&gt;
Calls to L_8c800 were removed from the following:&lt;br /&gt;
* L_640e0, prev ver @ L_640e0.&lt;br /&gt;
* L_643c0, prev ver @ L_643d0.&lt;br /&gt;
* L_65290, prev ver @ L_652a0.&lt;br /&gt;
* L_65da0, prev ver @ L_65e80.&lt;br /&gt;
&lt;br /&gt;
L_8c800 (in prev ver) just writes the input u8 (always 0 with these callers) into state.&lt;br /&gt;
&lt;br /&gt;
=== [[Migration_services|migration]] ===&lt;br /&gt;
* Updated L_12d5a0, prev ver at L_12d5a0.&lt;br /&gt;
** The &amp;lt;code&amp;gt;inw0&amp;gt;&amp;gt;17 &amp;gt; 0xA&amp;lt;/code&amp;gt; check at the end was replaced with &amp;lt;code&amp;gt;inw0 &amp;gt; 0x1600FF&amp;lt;/code&amp;gt;.&lt;br /&gt;
** This just updates the min_sysver value used during [[Migration_services#SendClientProfile|request message]] validation.&lt;br /&gt;
* Updated L_18dc40, prev ver at L_18dc40.&lt;br /&gt;
** Minor changes?&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
System update report(s):&lt;br /&gt;
* [https://yls8.mtheall.com/ninupdates/reports.php?date=2026-04-07_01-04-36&amp;amp;sys=hac]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{NavboxVersions}}&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14638</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14638"/>
		<updated>2026-04-30T17:46:39Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* SendClientProfile */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#SendClientProfile|SendClientProfile]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends [[#RequestServerProfile|RequestServerProfile]], then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
When the vfunc ret at the end of [[#WaitConnectionAsync|WaitConnectionAsync]] is true, the server just validates that the first 0x104-bytes of the above request match state. Otherwise when that vfunc ret is false:&lt;br /&gt;
* The ProductModel must be within [[Settings_services#ProductModel|range]] for Nintendo Switch / Nintendo Switch 2.&lt;br /&gt;
* Calls a func with the request SystemVersion and ProductModel, returning an error if false is returned.&lt;br /&gt;
** If &amp;lt;ProductModel is within the range for Nintendo Switch&amp;gt;: return SystemVersion == &amp;lt;SystemVersion value loaded for the server system&amp;gt;.&lt;br /&gt;
** Otherwise: return SystemVersion &amp;gt; &amp;lt;min_sysver&amp;gt; &amp;amp;&amp;amp; &amp;lt;ProductModel is within the range for Nintendo Switch 2&amp;gt;.&lt;br /&gt;
* Then the ClientProfile/ProductModel are copied into state, etc.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Settings_services&amp;diff=14637</id>
		<title>Settings services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Settings_services&amp;diff=14637"/>
		<updated>2026-04-30T17:20:24Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* ProductModel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= set =&lt;br /&gt;
This is &amp;quot;nn::settings::ISettingsServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetLanguageCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetAvailableLanguageCodes]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [4.0.0+] [[#MakeLanguageCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#GetAvailableLanguageCodeCount]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#GetRegionCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [4.0.0+] [[#GetAvailableLanguageCodes2]]&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [4.0.0+] [[#GetAvailableLanguageCodeCount2]]&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [4.0.0+] [[#GetKeyCodeMap]]&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [5.0.0+] [[#GetQuestFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 9 || [6.0.0+] [[#GetKeyCodeMap2]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [9.0.0+] [[#GetFirmwareVersionForDebug]]&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [10.1.0+] [[#GetDeviceNickName]]&lt;br /&gt;
|-&lt;br /&gt;
| 12 || [18.0.0+] GetKeyCodeMapByPort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[4.0.0+] Official user-processes now use GetAvailableLanguageCodes2/GetAvailableLanguageCodeCount2 instead of {original commands}.&lt;br /&gt;
&lt;br /&gt;
In official user-processes in the [[#Language]]-&amp;gt;[[#LanguageCode]] conversion function (MakeLanguageCode):&lt;br /&gt;
* During one-time init, GetAvailableLanguageCodes is used to initialize the LanguageCodes array cache, with max_entries=0xF (buffer size in u64s). [4.0.0+] GetAvailableLanguageCodes2 is now used with max_entries 0x40.&lt;br /&gt;
* [4.0.0+] When the input [[#Language]] is larger than the cached total_entries from the above command output, or [[#Language]] is negative, command MakeLanguageCode is used instead of the array.&lt;br /&gt;
&lt;br /&gt;
== GetLanguageCode ==&lt;br /&gt;
No input, returns an output [[#LanguageCode]]. This is the current system language.&lt;br /&gt;
&lt;br /&gt;
== GetAvailableLanguageCodes ==&lt;br /&gt;
Takes a type-0xA buffer containing the [[#LanguageCode]] output array, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== MakeLanguageCode ==&lt;br /&gt;
Takes an input [[#Language]], returns an output [[#LanguageCode]].&lt;br /&gt;
&lt;br /&gt;
== GetAvailableLanguageCodeCount ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== GetRegionCode ==&lt;br /&gt;
No input, returns a [[#RegionCode_2|RegionCode]].&lt;br /&gt;
&lt;br /&gt;
== GetAvailableLanguageCodes2 ==&lt;br /&gt;
Takes a type-0x6 buffer containing the [[#LanguageCode]] output array, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== GetAvailableLanguageCodeCount2 ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== GetKeyCodeMap ==&lt;br /&gt;
Takes a type-0x16 output buffer containing KeyCodeMap, official sw uses fixed size 0x1000. This is probably related to HID keyboard.&lt;br /&gt;
&lt;br /&gt;
== GetFirmwareVersionForDebug ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a 0x80-byte &amp;quot;nn::oe::FirmwareVersionForDebug&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This uses [[#GetDebugModeFlag]] internally, if the output flag is 0 an error is thrown.&lt;br /&gt;
&lt;br /&gt;
This runs the same code as GetFirmwareVersion2, with the last 0x80-bytes of the [[System_Version_Title|output]] being copied to the output buffer.&lt;br /&gt;
&lt;br /&gt;
= set:fd =&lt;br /&gt;
This is &amp;quot;nn::settings::IFirmwareDebugSettingsServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[4.0.0+] Only exposed if in [[SPL_services#IsDevelopment|development mode]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 2 || SetSettingsItemValue&lt;br /&gt;
|-&lt;br /&gt;
| 3 || ResetSettingsItemValue&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#ISettingsItemKeyIterator|CreateSettingsItemKeyIterator]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [4.0.0+] ReadSettings&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [4.0.0+] ResetSettings&lt;br /&gt;
|-&lt;br /&gt;
| 20 || [4.0.0+] SetWebInspectorFlag&lt;br /&gt;
|-&lt;br /&gt;
| 21 || [4.0.0+] SetAllowedSslHosts&lt;br /&gt;
|-&lt;br /&gt;
| 22 || [4.0.0+] SetHostFsMountPoint&lt;br /&gt;
|-&lt;br /&gt;
| 23 || [9.0.0+] SetMemoryUsageRateFlag&lt;br /&gt;
|-&lt;br /&gt;
| 24 || [20.0.0+] CommitSettings&lt;br /&gt;
|-&lt;br /&gt;
| 27 || [21.0.0+] SetHttpAuthConfigs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ISettingsItemKeyIterator ==&lt;br /&gt;
This is &amp;quot;nn::settings::ISettingsItemKeyIterator&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GoNext&lt;br /&gt;
|-&lt;br /&gt;
| 1 || GetKeySize&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GetKey&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= set:cal =&lt;br /&gt;
This is &amp;quot;nn::settings::IFactorySettingsServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [S1] [[#GetBluetoothBdAddress]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetConfigurationId1]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [S1] [[#GetAccelerometerOffset]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [S1] [[#GetAccelerometerScale]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [S1] [[#GetGyroscopeOffset]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [S1] [[#GetGyroscopeScale]]&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [[#GetWirelessLanMacAddress]]&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [S1] [[#GetWirelessLanCountryCodeCount]]&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [S1] [[#GetWirelessLanCountryCodes]]&lt;br /&gt;
|-&lt;br /&gt;
| 9 || [[#GetSerialNumber]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [S1] [[#SetInitialSystemAppletProgramId]]&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [S1] [[#SetOverlayDispProgramId]]&lt;br /&gt;
|-&lt;br /&gt;
| 12 || [[#GetBatteryLot]]&lt;br /&gt;
|-&lt;br /&gt;
| 14 || [S1] [[#GetEciDeviceCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 15 || [S1] [[#GetEticketDeviceCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 16 || [S1] [[#GetSslKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 17 || [S1] [[#GetSslCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 18 || [S1] [[#GetGameCardKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 19 || [S1] [[#GetGameCardCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 20 || [S1] [[#GetEciDeviceKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 21 || [S1] [[#GetEticketDeviceKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 22 || [S1] [[#GetSpeakerParameter]]&lt;br /&gt;
|-&lt;br /&gt;
| 23 || [S1] [4.0.0+] [[#GetLcdVendorId]]&lt;br /&gt;
|-&lt;br /&gt;
| 24 || [S1] [5.0.0+] [[#GetEciDeviceCertificate2]]&lt;br /&gt;
|-&lt;br /&gt;
| 25 || [S1] [5.0.0+] [[#GetEciDeviceKey2]]&lt;br /&gt;
|-&lt;br /&gt;
| 26 || [S1] [5.0.0+] [[#GetAmiiboKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 27 || [S1] [5.0.0+] [[#GetAmiiboEcqvCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 28 || [S1] [5.0.0+] [[#GetAmiiboEcdsaCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 29 || [S1] [5.0.0+] [[#GetAmiiboEcqvBlsKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 30 || [S1] [5.0.0+] [[#GetAmiiboEcqvBlsCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 31 || [S1] [5.0.0+] [[#GetAmiiboEcqvBlsRootCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 32 || [S1] [5.0.0+] [[#GetUsbTypeCPowerSourceCircuitVersion]]&lt;br /&gt;
|-&lt;br /&gt;
| 33 || [S1] [8.1.1+] [[#GetAnalogStickModuleTypeL]]&lt;br /&gt;
|-&lt;br /&gt;
| 34 || [S1] [8.1.1+] [[#GetAnalogStickModelParameterL]]&lt;br /&gt;
|-&lt;br /&gt;
| 35 || [S1] [8.1.1+] [[#GetAnalogStickFactoryCalibrationL]]&lt;br /&gt;
|-&lt;br /&gt;
| 36 || [S1] [8.1.1+] [[#GetAnalogStickModuleTypeR]]&lt;br /&gt;
|-&lt;br /&gt;
| 37 || [S1] [8.1.1+] [[#GetAnalogStickModelParameterR]]&lt;br /&gt;
|-&lt;br /&gt;
| 38 || [S1] [8.1.1+] [[#GetAnalogStickFactoryCalibrationR]]&lt;br /&gt;
|-&lt;br /&gt;
| 39 || [S1] [8.1.1+] [[#GetConsoleSixAxisSensorModuleType]]&lt;br /&gt;
|-&lt;br /&gt;
| 40 || [S1] [8.1.1+] [[#GetConsoleSixAxisSensorHorizontalOffset]]&lt;br /&gt;
|-&lt;br /&gt;
| 41 || [S1] [6.0.0+] [[#GetBatteryVersion]]&lt;br /&gt;
|-&lt;br /&gt;
| 42 || [S1] [10.0.0+] [[#GetDeviceId]]&lt;br /&gt;
|-&lt;br /&gt;
| 43 || [S1] [10.0.0+] [[#GetConsoleSixAxisSensorMountType]]&lt;br /&gt;
|-&lt;br /&gt;
| 44 || [S2] GetCpDeviceKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 45 || [S2] GetCpDeviceKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 46 || [S2] GetCpCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 47 || [S2] GetCpCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 48 || [S2] GetRaCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 49 || [S2] GetRaCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 50 || [S2] GetRaOemEkFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 51 || [S2] GetRaOemEkFile&lt;br /&gt;
|-&lt;br /&gt;
| 52 || [S2] GetRaPkaKekFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 53 || [S2] GetRaPkaKekFile&lt;br /&gt;
|-&lt;br /&gt;
| 54 || [S2] GetGcNxPkKekFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 55 || [S2] GetGcNxPkKekFile&lt;br /&gt;
|-&lt;br /&gt;
| 56 || [S2] GetGcUniqueImportKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 57 || [S2] GetGcUniqueImportKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 58 || [S2] GetGcUniqueEncryptionKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 59 || [S2] GetGcUniqueEncryptionKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 60 || [S2] GetGcCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 61 || [S2] GetGcCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 62 || [S2] GetGcUniqueKeyAFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 63 || [S2] GetGcUniqueKeyAFile&lt;br /&gt;
|-&lt;br /&gt;
| 64 || [S2] GetGcUniqueKeyBFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 65 || [S2] GetGcUniqueKeyBFile&lt;br /&gt;
|-&lt;br /&gt;
| 66 || [S2] GetGcNxKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 67 || [S2] GetGcNxKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 68 || [S2] GetGcNxCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 69 || [S2] GetGcNxCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 70 || [S2] GetWirelessLanRegulatoryDomain&lt;br /&gt;
|-&lt;br /&gt;
| 71 || [S2] GetDeviceId&lt;br /&gt;
|-&lt;br /&gt;
| 72 || [S2] GetBluetoothBdAddressSet&lt;br /&gt;
|-&lt;br /&gt;
| 73 || [S2] GetToolModel&lt;br /&gt;
|-&lt;br /&gt;
| 74 || [S2] IsRadioForbidden&lt;br /&gt;
|-&lt;br /&gt;
| 75 || [S2] GetDisplayModuleId&lt;br /&gt;
|-&lt;br /&gt;
| 76 || [S2] GetAnalogStickModuleTypeL&lt;br /&gt;
|-&lt;br /&gt;
| 77 || [S2] GetAnalogStickModelParameterL&lt;br /&gt;
|-&lt;br /&gt;
| 78 || [S2] GetAnalogStickFactoryCalibrationL&lt;br /&gt;
|-&lt;br /&gt;
| 79 || [S2] GetAnalogStickModuleTypeR&lt;br /&gt;
|-&lt;br /&gt;
| 80 || [S2] GetAnalogStickModelParameterR&lt;br /&gt;
|-&lt;br /&gt;
| 81 || [S2] GetAnalogStickFactoryCalibrationR&lt;br /&gt;
|-&lt;br /&gt;
| 82 || [S2] GetConsoleSixAxisSensorModuleType&lt;br /&gt;
|-&lt;br /&gt;
| 83 || [S2] GetConsoleSixAxisSensorMountType&lt;br /&gt;
|-&lt;br /&gt;
| 84 || [S2] GetConsoleSixAxisSensorFactoryCalibration&lt;br /&gt;
|-&lt;br /&gt;
| 85 || [S2] GetOta0DeviceKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 86 || [S2] GetOta0DeviceKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 87 || [S2] GetOta0CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 88 || [S2] GetOta0CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 89 || [S2] GetOta1DeviceKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 90 || [S2] GetOta1DeviceKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 91 || [S2] GetOta1CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 92 || [S2] GetOta1CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 93 || [S2] GetOta2DeviceKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 94 || [S2] GetOta2DeviceKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 95 || [S2] GetOta2CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 96 || [S2] GetOta2CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 97 || [S2] GetJc0CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 98 || [S2] GetJc0CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 99 || [S2] GetJc0PrivateKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [S2] GetJc0PrivateKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [S2] GetJc0PkKekFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [S2] GetJc0PkKekFile&lt;br /&gt;
|-&lt;br /&gt;
| 103 || [S2] GetJc1CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 104 || [S2] GetJc1CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 105 || [S2] GetJc1PrivateKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 106 || [S2] GetJc1PrivateKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 107 || [S2] GetJc1PkKekFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 108 || [S2] GetJc1PkKekFile&lt;br /&gt;
|-&lt;br /&gt;
| 109 || [S2] GetWirelessLanPowerTable&lt;br /&gt;
|-&lt;br /&gt;
| 110 || [S2] GetConsoleSixAxisSensorFactoryAccelerationLog&lt;br /&gt;
|-&lt;br /&gt;
| 111 || [S2] GetDrmCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 112 || [S2] GetDrmCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 113 || [S2] GetCalibrationTimeStampUtc&lt;br /&gt;
|-&lt;br /&gt;
| 114 || [S2] GetEncryptedSecretDeviceIdFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 115 || [S2] GetEncryptedSecretDeviceIdFile&lt;br /&gt;
|-&lt;br /&gt;
| 116 || [S2] GetEncryptedSecretDeviceIdEncryptionKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 117 || [S2] GetEncryptedSecretDeviceIdEncryptionKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 118 || [S2] &lt;br /&gt;
|-&lt;br /&gt;
| 119 || [22.0.0+] GetRegionCode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Used for accessing data [[Calibration|calibrated]] at the factory.&lt;br /&gt;
&lt;br /&gt;
== GetBluetoothBdAddress ==&lt;br /&gt;
No input. Returns a [[#BdAddress|BdAddress]].&lt;br /&gt;
&lt;br /&gt;
== GetConfigurationId1 ==&lt;br /&gt;
No input. Returns a [[#ConfigurationId1|ConfigurationId1]].&lt;br /&gt;
&lt;br /&gt;
== GetAccelerometerOffset ==&lt;br /&gt;
No input. Returns a [[#AccelerometerOffset|AccelerometerOffset]].&lt;br /&gt;
&lt;br /&gt;
== GetAccelerometerScale ==&lt;br /&gt;
No input. Returns a [[#AccelerometerScale|AccelerometerScale]].&lt;br /&gt;
&lt;br /&gt;
== GetGyroscopeOffset ==&lt;br /&gt;
No input. Returns a [[#GyroscopeOffset|GyroscopeOffset]].&lt;br /&gt;
&lt;br /&gt;
== GetGyroscopeScale ==&lt;br /&gt;
No input. Returns a [[#GyroscopeScale|GyroscopeScale]].&lt;br /&gt;
&lt;br /&gt;
== GetWirelessLanMacAddress ==&lt;br /&gt;
No input. Returns a [[#MacAddress|MacAddress]].&lt;br /&gt;
&lt;br /&gt;
== GetWirelessLanCountryCodeCount ==&lt;br /&gt;
No input. Returns a s32 &#039;&#039;&#039;OutCount&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== GetWirelessLanCountryCodes ==&lt;br /&gt;
Takes a type-0x16 output buffer containing an array of [[#CountryCode|CountryCode]]. Returns a s32 &#039;&#039;&#039;OutCount&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
== GetSerialNumber ==&lt;br /&gt;
No input. Returns a [[#SerialNumber|SerialNumber]].&lt;br /&gt;
&lt;br /&gt;
== SetInitialSystemAppletProgramId ==&lt;br /&gt;
Takes an input [[NCM_services#ProgramId|ProgramId]]. No output.&lt;br /&gt;
&lt;br /&gt;
== SetOverlayDispProgramId ==&lt;br /&gt;
Takes an input [[NCM_services#ProgramId|ProgramId]]. No output.&lt;br /&gt;
&lt;br /&gt;
== GetBatteryLot ==&lt;br /&gt;
No input. Returns a [[#BatteryLot|BatteryLot]].&lt;br /&gt;
&lt;br /&gt;
== GetEciDeviceCertificate ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#EccB233DeviceCertificate|EccB233DeviceCertificate]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the device certificate (ECC signed). This is identical to 3DS DeviceCert/CTCert besides the strings. NIM loads the DeviceId from this.&lt;br /&gt;
&lt;br /&gt;
== GetEticketDeviceCertificate ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#Rsa2048DeviceCertificate|Rsa2048DeviceCertificate]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the ETicket certificate (RSA signed).&lt;br /&gt;
&lt;br /&gt;
== GetSslKey ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#SslKey|SslKey]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the extended SSL key (0x130 bytes) from [[Calibration#CAL0|CAL0]]. If the extended key is not programmed then it falls back to the normal SSL key (0x110 bytes).&lt;br /&gt;
&lt;br /&gt;
Used by SSL-sysmodule, see [[SSL_services|here]].&lt;br /&gt;
&lt;br /&gt;
== GetSslCertificate ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#SslCertificate|SslCertificate]]. No output.&lt;br /&gt;
&lt;br /&gt;
Used by SSL-sysmodule, see [[SSL_services|here]].&lt;br /&gt;
&lt;br /&gt;
== GetGameCardKey ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#GameCardKey|GameCardKey]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the extended GameCard key (0x130 bytes) from [[Calibration#CAL0|CAL0]]. If the extended key is not programmed then it falls back to the normal GameCard key (0x110 bytes).&lt;br /&gt;
&lt;br /&gt;
== GetGameCardCertificate ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#GameCardCertificate|GameCardCertificate]]. No output.&lt;br /&gt;
&lt;br /&gt;
== GetEciDeviceKey ==&lt;br /&gt;
No input. Returns an [[#EccB233DeviceKey|EccB233DeviceKey]].&lt;br /&gt;
&lt;br /&gt;
Returns the extended device ECC-B233 key (0x50 bytes) from [[Calibration#CAL0|CAL0]]. If the extended key is not programmed then it falls back to the normal device ECC-B233 key (0x30 bytes).&lt;br /&gt;
&lt;br /&gt;
== GetEticketDeviceKey ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#Rsa2048DeviceKey|Rsa2048DeviceKey]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the extended ETicket RSA-2048 key (0x240 bytes) from [[Calibration#CAL0|CAL0]]. If the extended key is not programmed then it falls back to the normal ETicket RSA-2048 key (0x220 bytes).&lt;br /&gt;
&lt;br /&gt;
== GetSpeakerParameter ==&lt;br /&gt;
No input. Returns a [[#SpeakerParameter|SpeakerParameter]].&lt;br /&gt;
&lt;br /&gt;
== GetLcdVendorId ==&lt;br /&gt;
No input. Returns a [[Calibration#LcdVendorId|LcdVendorId]].&lt;br /&gt;
&lt;br /&gt;
== GetEciDeviceCertificate2 ==&lt;br /&gt;
Same as [[#GetEciDeviceCertificate]], but returns a [[#Rsa2048DeviceCertificate|RSA-2048]] variant of the device certificate.&lt;br /&gt;
&lt;br /&gt;
== GetEciDeviceKey2 ==&lt;br /&gt;
Same as [[#GetEciDeviceKey]], but returns a [[#Rsa2048DeviceKey|RSA-2048]] variant of the device key.&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboKey ==&lt;br /&gt;
No input. Returns an [[#AmiiboKey|AmiiboKey]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcqvCertificate ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcqvCertificate|AmiiboEcqvCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcdsaCertificate ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcdsaCertificate|AmiiboEcdsaCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcqvBlsKey ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcqvBlsKey|AmiiboEcqvBlsKey]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcqvBlsCertificate ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcqvBlsCertificate|AmiiboEcqvBlsCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcqvBlsRootCertificate ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcqvBlsRootCertificate|AmiiboEcqvBlsRootCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetUsbTypeCPowerSourceCircuitVersion ==&lt;br /&gt;
No input. Returns an [[Calibration#UsbTypeCPowerSourceCircuit|UsbTypeCPowerSourceCircuitVersion]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickModuleTypeL ==&lt;br /&gt;
No input. Returns an [[Calibration#AnalogStickModuleType|AnalogStickModuleType]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickModelParameterL ==&lt;br /&gt;
No input. Returns an [[#AnalogStickModelParameter|AnalogStickModelParameter]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickFactoryCalibrationL ==&lt;br /&gt;
No input. Returns an [[#AnalogStickFactoryCalibration|AnalogStickFactoryCalibration]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickModuleTypeR ==&lt;br /&gt;
No input. Returns an [[Calibration#AnalogStickModuleType|AnalogStickModuleType]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickModelParameterR ==&lt;br /&gt;
No input. Returns an [[#AnalogStickModelParameter|AnalogStickModelParameter]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickFactoryCalibrationR ==&lt;br /&gt;
No input. Returns an [[#AnalogStickFactoryCalibration|AnalogStickFactoryCalibration]].&lt;br /&gt;
&lt;br /&gt;
== GetConsoleSixAxisSensorModuleType ==&lt;br /&gt;
No input. Returns a [[Calibration#ConsoleSixAxisSensorModuleType|ConsoleSixAxisSensorModuleType]].&lt;br /&gt;
&lt;br /&gt;
== GetConsoleSixAxisSensorHorizontalOffset ==&lt;br /&gt;
No input. Returns a [[#ConsoleSixAxisSensorHorizontalOffset|ConsoleSixAxisSensorHorizontalOffset]].&lt;br /&gt;
&lt;br /&gt;
== GetBatteryVersion ==&lt;br /&gt;
No input. Returns a [[Calibration#BatteryVersion|BatteryVersion]].&lt;br /&gt;
&lt;br /&gt;
== GetDeviceId ==&lt;br /&gt;
No input. Returns an u64 &#039;&#039;&#039;DeviceId&#039;&#039;&#039; by reading and converting the hexadecimal string at offset 0xC6 inside [[#EccB233DeviceCertificate]] or [[#Rsa2048DeviceCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetConsoleSixAxisSensorMountType ==&lt;br /&gt;
No input. Returns a [[Calibration#ConsoleSixAxisSensorMountType|ConsoleSixAxisSensorMountType]].&lt;br /&gt;
&lt;br /&gt;
= set:sys =&lt;br /&gt;
This is &amp;quot;nn::settings::ISystemSettingsServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#SetLanguageCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SetNetworkSettings&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GetNetworkSettings&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [S1] [[#GetFirmwareVersion]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [3.0.0+] GetFirmwareVersion2&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [S1] [5.0.0+] GetFirmwareVersionDigest&lt;br /&gt;
|-&lt;br /&gt;
| 7 || GetLockScreenFlag&lt;br /&gt;
|-&lt;br /&gt;
| 8 || SetLockScreenFlag&lt;br /&gt;
|-&lt;br /&gt;
| 9 || GetBacklightSettings&lt;br /&gt;
|-&lt;br /&gt;
| 10 || SetBacklightSettings&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [S1] SetBluetoothDevicesSettings&lt;br /&gt;
|-&lt;br /&gt;
| 12 || [S1] GetBluetoothDevicesSettings&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetExternalSteadyClockSourceId&lt;br /&gt;
|-&lt;br /&gt;
| 14 || SetExternalSteadyClockSourceId&lt;br /&gt;
|-&lt;br /&gt;
| 15 || GetUserSystemClockContext&lt;br /&gt;
|-&lt;br /&gt;
| 16 || SetUserSystemClockContext&lt;br /&gt;
|-&lt;br /&gt;
| 17 || [[#GetAccountSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 18 || [[#SetAccountSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 19 || GetAudioVolume&lt;br /&gt;
|-&lt;br /&gt;
| 20 || SetAudioVolume&lt;br /&gt;
|-&lt;br /&gt;
| 21 || [[#GetEulaVersions]]&lt;br /&gt;
|-&lt;br /&gt;
| 22 || [[#SetEulaVersions]]&lt;br /&gt;
|-&lt;br /&gt;
| 23 || [[#GetColorSetId]]&lt;br /&gt;
|-&lt;br /&gt;
| 24 || [[#SetColorSetId]]&lt;br /&gt;
|-&lt;br /&gt;
| 25 || [S1] GetConsoleInformationUploadFlag&lt;br /&gt;
|-&lt;br /&gt;
| 26 || [S1] SetConsoleInformationUploadFlag&lt;br /&gt;
|-&lt;br /&gt;
| 27 || [S1] GetAutomaticApplicationDownloadFlag&lt;br /&gt;
|-&lt;br /&gt;
| 28 || [S1] SetAutomaticApplicationDownloadFlag&lt;br /&gt;
|-&lt;br /&gt;
| 29 || [[#GetNotificationSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 30 || [[#SetNotificationSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 31 || [[#GetAccountNotificationSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 32 || [[#SetAccountNotificationSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 35 || GetVibrationMasterVolume&lt;br /&gt;
|-&lt;br /&gt;
| 36 || SetVibrationMasterVolume&lt;br /&gt;
|-&lt;br /&gt;
| 37 || GetSettingsItemValueSize&lt;br /&gt;
|-&lt;br /&gt;
| 38 || [[#GetSettingsItemValue]]&lt;br /&gt;
|-&lt;br /&gt;
| 39 || [[#GetTvSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 40 || [[#SetTvSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 41 || GetEdid&lt;br /&gt;
|-&lt;br /&gt;
| 42 || SetEdid&lt;br /&gt;
|-&lt;br /&gt;
| 43 || GetAudioOutputMode&lt;br /&gt;
|-&lt;br /&gt;
| 44 || SetAudioOutputMode&lt;br /&gt;
|-&lt;br /&gt;
| 45 || GetSpeakerAutoMuteFlag ([1.0.0-12.1.0] IsForceMuteOnHeadphoneRemoved)&lt;br /&gt;
|-&lt;br /&gt;
| 46 || SetSpeakerAutoMuteFlag ([1.0.0-12.1.0] SetForceMuteOnHeadphoneRemoved)&lt;br /&gt;
|-&lt;br /&gt;
| 47 || [[#GetQuestFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 48 || SetQuestFlag&lt;br /&gt;
|-&lt;br /&gt;
| 49 || [S1] [[#GetDataDeletionSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 50 || [S1] [[#SetDataDeletionSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 51 || [S1] GetInitialSystemAppletProgramId&lt;br /&gt;
|-&lt;br /&gt;
| 52 || [S1] GetOverlayDispProgramId&lt;br /&gt;
|-&lt;br /&gt;
| 53 || GetDeviceTimeZoneLocationName&lt;br /&gt;
|-&lt;br /&gt;
| 54 || SetDeviceTimeZoneLocationName&lt;br /&gt;
|-&lt;br /&gt;
| 55 || [S1] [[#GetWirelessCertificationFileSize]]&lt;br /&gt;
|-&lt;br /&gt;
| 56 || [S1] [[#GetWirelessCertificationFile]]&lt;br /&gt;
|-&lt;br /&gt;
| 57 || [[#SetRegionCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 58 || GetNetworkSystemClockContext&lt;br /&gt;
|-&lt;br /&gt;
| 59 || SetNetworkSystemClockContext&lt;br /&gt;
|-&lt;br /&gt;
| 60 || IsUserSystemClockAutomaticCorrectionEnabled&lt;br /&gt;
|-&lt;br /&gt;
| 61 || SetUserSystemClockAutomaticCorrectionEnabled&lt;br /&gt;
|-&lt;br /&gt;
| 62 || [[#GetDebugModeFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 63 || [[#GetPrimaryAlbumStorage]]&lt;br /&gt;
|-&lt;br /&gt;
| 64 || [[#SetPrimaryAlbumStorage]]&lt;br /&gt;
|-&lt;br /&gt;
| 65 || [S1] GetUsb30EnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 66 || [S1] SetUsb30EnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 67 || [[#GetBatteryLot]]&lt;br /&gt;
|-&lt;br /&gt;
| 68 || [[#GetSerialNumber]]&lt;br /&gt;
|-&lt;br /&gt;
| 69 || GetNfcEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 70 || SetNfcEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 71 || [[#GetSleepSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 72 || [[#SetSleepSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 73 || GetWirelessLanEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 74 || SetWirelessLanEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 75 || [S1] [[#GetInitialLaunchSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 76 || [S1] [[#SetInitialLaunchSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 77 || [[#GetDeviceNickName]]&lt;br /&gt;
|-&lt;br /&gt;
| 78 || [[#SetDeviceNickName]]&lt;br /&gt;
|-&lt;br /&gt;
| 79 || [[#GetProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 80 || [S1] GetLdnChannel&lt;br /&gt;
|-&lt;br /&gt;
| 81 || [S1] SetLdnChannel&lt;br /&gt;
|-&lt;br /&gt;
| 82 || AcquireTelemetryDirtyFlagEventHandle&lt;br /&gt;
|-&lt;br /&gt;
| 83 || GetTelemetryDirtyFlags&lt;br /&gt;
|-&lt;br /&gt;
| 84 || GetPtmBatteryLot&lt;br /&gt;
|-&lt;br /&gt;
| 85 || SetPtmBatteryLot&lt;br /&gt;
|-&lt;br /&gt;
| 86 || GetPtmFuelGaugeParameter&lt;br /&gt;
|-&lt;br /&gt;
| 87 || SetPtmFuelGaugeParameter&lt;br /&gt;
|-&lt;br /&gt;
| 88 || GetBluetoothEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 89 || SetBluetoothEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 90 || [[#GetMiiAuthorId]]&lt;br /&gt;
|-&lt;br /&gt;
| 91 || SetShutdownRtcValue&lt;br /&gt;
|-&lt;br /&gt;
| 92 || GetShutdownRtcValue&lt;br /&gt;
|-&lt;br /&gt;
| 93 || AcquireFatalDirtyFlagEventHandle&lt;br /&gt;
|-&lt;br /&gt;
| 94 || GetFatalDirtyFlags&lt;br /&gt;
|-&lt;br /&gt;
| 95 || [2.0.0+] GetAutoUpdateEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 96 || [2.0.0+] SetAutoUpdateEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 97 || [S1] [2.0.0+] GetNxControllerSettings&lt;br /&gt;
|-&lt;br /&gt;
| 98 || [S1] [2.0.0+] SetNxControllerSettings&lt;br /&gt;
|-&lt;br /&gt;
| 99 || [2.0.0+] GetBatteryPercentageFlag&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [2.0.0+] SetBatteryPercentageFlag&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [S1] [2.0.0+] GetExternalRtcResetFlag&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [S1] [2.0.0+] SetExternalRtcResetFlag&lt;br /&gt;
|-&lt;br /&gt;
| 103 || [3.0.0+] GetUsbFullKeyEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 104 || [3.0.0+] SetUsbFullKeyEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 105 || [3.0.0+] SetExternalSteadyClockInternalOffset&lt;br /&gt;
|-&lt;br /&gt;
| 106 || [3.0.0+] GetExternalSteadyClockInternalOffset&lt;br /&gt;
|-&lt;br /&gt;
| 107 || [3.0.0+] GetBacklightSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 108 || [3.0.0+] SetBacklightSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 109 || [3.0.0+] GetHeadphoneVolumeWarningCount&lt;br /&gt;
|-&lt;br /&gt;
| 110 || [3.0.0+] SetHeadphoneVolumeWarningCount&lt;br /&gt;
|-&lt;br /&gt;
| 111 || [S1] [3.0.0+] GetBluetoothAfhEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 112 || [S1] [3.0.0+] SetBluetoothAfhEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 113 || [S1] [3.0.0+] GetBluetoothBoostEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 114 || [S1] [3.0.0+] SetBluetoothBoostEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 115 || [3.0.0+] GetInRepairProcessEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 116 || [3.0.0+] SetInRepairProcessEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 117 || [S1] [3.0.0+] GetHeadphoneVolumeUpdateFlag&lt;br /&gt;
|-&lt;br /&gt;
| 118 || [S1] [3.0.0+] SetHeadphoneVolumeUpdateFlag&lt;br /&gt;
|-&lt;br /&gt;
| 119 || [3.0.0-14.1.2] NeedsToUpdateHeadphoneVolume&lt;br /&gt;
|-&lt;br /&gt;
| 120 || [3.0.0+] GetPushNotificationActivityModeOnSleep&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [3.0.0+] SetPushNotificationActivityModeOnSleep&lt;br /&gt;
|-&lt;br /&gt;
| 122 || [4.0.0+] [[#GetServiceDiscoveryControlSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 123 || [4.0.0+] SetServiceDiscoveryControlSettings&lt;br /&gt;
|-&lt;br /&gt;
| 124 || [4.0.0+] [[#GetErrorReportSharePermission]]&lt;br /&gt;
|-&lt;br /&gt;
| 125 || [4.0.0+] [[#SetErrorReportSharePermission]]&lt;br /&gt;
|-&lt;br /&gt;
| 126 || [4.0.0+] [[#GetAppletLaunchFlags]]&lt;br /&gt;
|-&lt;br /&gt;
| 127 || [4.0.0+] [[#SetAppletLaunchFlags]]&lt;br /&gt;
|-&lt;br /&gt;
| 128 || [S1] [4.0.0+] GetConsoleSixAxisSensorAccelerationBias&lt;br /&gt;
|-&lt;br /&gt;
| 129 || [S1] [4.0.0+] SetConsoleSixAxisSensorAccelerationBias&lt;br /&gt;
|-&lt;br /&gt;
| 130 || [S1] [4.0.0+] GetConsoleSixAxisSensorAngularVelocityBias&lt;br /&gt;
|-&lt;br /&gt;
| 131 || [S1] [4.0.0+] SetConsoleSixAxisSensorAngularVelocityBias&lt;br /&gt;
|-&lt;br /&gt;
| 132 || [S1] [4.0.0+] GetConsoleSixAxisSensorAccelerationGain&lt;br /&gt;
|-&lt;br /&gt;
| 133 || [S1] [4.0.0+] SetConsoleSixAxisSensorAccelerationGain&lt;br /&gt;
|-&lt;br /&gt;
| 134 || [S1] [4.0.0+] GetConsoleSixAxisSensorAngularVelocityGain&lt;br /&gt;
|-&lt;br /&gt;
| 135 || [S1] [4.0.0+] SetConsoleSixAxisSensorAngularVelocityGain&lt;br /&gt;
|-&lt;br /&gt;
| 136 || [4.0.0+] [[#GetKeyboardLayout]]&lt;br /&gt;
|-&lt;br /&gt;
| 137 || [4.0.0+] [[#SetKeyboardLayout]]&lt;br /&gt;
|-&lt;br /&gt;
| 138 || [4.0.0+] GetWebInspectorFlag&lt;br /&gt;
|-&lt;br /&gt;
| 139 || [4.0.0+] [[#GetAllowedSslHosts]]&lt;br /&gt;
|-&lt;br /&gt;
| 140 || [4.0.0+] GetHostFsMountPoint&lt;br /&gt;
|-&lt;br /&gt;
| 141 || [5.0.0+] GetRequiresRunRepairTimeReviser&lt;br /&gt;
|-&lt;br /&gt;
| 142 || [5.0.0+] SetRequiresRunRepairTimeReviser&lt;br /&gt;
|-&lt;br /&gt;
| 143 || [S1] [5.0.0+] SetBlePairingSettings&lt;br /&gt;
|-&lt;br /&gt;
| 144 || [S1] [5.0.0+] GetBlePairingSettings&lt;br /&gt;
|-&lt;br /&gt;
| 145 || [S1] [5.0.0+] GetConsoleSixAxisSensorAngularVelocityTimeBias&lt;br /&gt;
|-&lt;br /&gt;
| 146 || [S1] [5.0.0+] SetConsoleSixAxisSensorAngularVelocityTimeBias&lt;br /&gt;
|-&lt;br /&gt;
| 147 || [S1] [5.0.0+] GetConsoleSixAxisSensorAngularAcceleration&lt;br /&gt;
|-&lt;br /&gt;
| 148 || [S1] [5.0.0+] SetConsoleSixAxisSensorAngularAcceleration&lt;br /&gt;
|-&lt;br /&gt;
| 149 || [5.0.0+] [[#GetRebootlessSystemUpdateVersion]]&lt;br /&gt;
|-&lt;br /&gt;
| 150 || [5.0.0+] GetDeviceTimeZoneLocationUpdatedTime&lt;br /&gt;
|-&lt;br /&gt;
| 151 || [5.0.0+] SetDeviceTimeZoneLocationUpdatedTime&lt;br /&gt;
|-&lt;br /&gt;
| 152 || [6.0.0+] GetUserSystemClockAutomaticCorrectionUpdatedTime&lt;br /&gt;
|-&lt;br /&gt;
| 153 || [6.0.0+] SetUserSystemClockAutomaticCorrectionUpdatedTime&lt;br /&gt;
|-&lt;br /&gt;
| 154 || [S1] [6.0.0+] GetAccountOnlineStorageSettings&lt;br /&gt;
|-&lt;br /&gt;
| 155 || [S1] [6.0.0+] SetAccountOnlineStorageSettings&lt;br /&gt;
|-&lt;br /&gt;
| 156 || [S1] [6.0.0+] GetPctlReadyFlag&lt;br /&gt;
|-&lt;br /&gt;
| 157 || [S1] [6.0.0+] SetPctlReadyFlag&lt;br /&gt;
|-&lt;br /&gt;
| 158 || [S1] [8.1.1+] GetAnalogStickUserCalibrationL&lt;br /&gt;
|-&lt;br /&gt;
| 159 || [S1] [8.1.1+] SetAnalogStickUserCalibrationL&lt;br /&gt;
|-&lt;br /&gt;
| 160 || [S1] [8.1.1+] GetAnalogStickUserCalibrationR&lt;br /&gt;
|-&lt;br /&gt;
| 161 || [S1] [8.1.1+] SetAnalogStickUserCalibrationR&lt;br /&gt;
|-&lt;br /&gt;
| 162 || [6.0.0+] GetPtmBatteryVersion&lt;br /&gt;
|-&lt;br /&gt;
| 163 || [6.0.0+] SetPtmBatteryVersion&lt;br /&gt;
|-&lt;br /&gt;
| 164 || [6.0.0+] GetUsb30HostEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 165 || [6.0.0+] SetUsb30HostEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 166 || [6.0.0+] GetUsb30DeviceEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 167 || [6.0.0+] SetUsb30DeviceEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 168 || [S1] [7.0.0+] GetThemeId&lt;br /&gt;
|-&lt;br /&gt;
| 169 || [S1] [7.0.0+] SetThemeId&lt;br /&gt;
|-&lt;br /&gt;
| 170 || [7.0.0+] [[#GetChineseTraditionalInputMethod]]&lt;br /&gt;
|-&lt;br /&gt;
| 171 || [7.0.0+] [[#SetChineseTraditionalInputMethod]]&lt;br /&gt;
|-&lt;br /&gt;
| 172 || [7.0.0+] GetPtmCycleCountReliability&lt;br /&gt;
|-&lt;br /&gt;
| 173 || [7.0.0+] SetPtmCycleCountReliability&lt;br /&gt;
|-&lt;br /&gt;
| 174 || [8.1.1+] [[#GetHomeMenuScheme]]&lt;br /&gt;
|-&lt;br /&gt;
| 175 || [S1] [7.0.0+] GetThemeSettings&lt;br /&gt;
|-&lt;br /&gt;
| 176 || [S1] [7.0.0+] SetThemeSettings&lt;br /&gt;
|-&lt;br /&gt;
| 177 || [S1] [7.0.0+] GetThemeKey&lt;br /&gt;
|-&lt;br /&gt;
| 178 || [S1] [7.0.0+] SetThemeKey&lt;br /&gt;
|-&lt;br /&gt;
| 179 || [8.0.0+] GetZoomFlag&lt;br /&gt;
|-&lt;br /&gt;
| 180 || [8.0.0+] SetZoomFlag&lt;br /&gt;
|-&lt;br /&gt;
| 181 || [S1] [8.0.0+] [[#GetT]]&lt;br /&gt;
|-&lt;br /&gt;
| 182 || [S1] [8.0.0+] [[#SetT]]&lt;br /&gt;
|-&lt;br /&gt;
| 183 || [9.0.0+] [[#GetPlatformRegion]]&lt;br /&gt;
|-&lt;br /&gt;
| 184 || [9.0.0+] [[#SetPlatformRegion]]&lt;br /&gt;
|-&lt;br /&gt;
| 185 || [9.0.0+] [[#GetHomeMenuSchemeModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 186 || [9.0.0+] [[#GetMemoryUsageRateFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 187 || [S1] [9.0.0+] [[#GetTouchScreenMode]]&lt;br /&gt;
|-&lt;br /&gt;
| 188 || [S1] [9.0.0+] [[#SetTouchScreenMode]]&lt;br /&gt;
|-&lt;br /&gt;
| 189 || [S1] [10.0.0+] [[#GetButtonConfigSettingsFull]]&lt;br /&gt;
|-&lt;br /&gt;
| 190 || [S1] [10.0.0+] [[#SetButtonConfigSettingsFull]]&lt;br /&gt;
|-&lt;br /&gt;
| 191 || [S1] [10.0.0+] [[#GetButtonConfigSettingsEmbedded]]&lt;br /&gt;
|-&lt;br /&gt;
| 192 || [S1] [10.0.0+] [[#SetButtonConfigSettingsEmbedded]]&lt;br /&gt;
|-&lt;br /&gt;
| 193 || [S1] [10.0.0+] [[#GetButtonConfigSettingsLeft]]&lt;br /&gt;
|-&lt;br /&gt;
| 194 || [S1] [10.0.0+] [[#SetButtonConfigSettingsLeft]]&lt;br /&gt;
|-&lt;br /&gt;
| 195 || [S1] [10.0.0+] [[#GetButtonConfigSettingsRight]]&lt;br /&gt;
|-&lt;br /&gt;
| 196 || [S1] [10.0.0+] [[#SetButtonConfigSettingsRight]]&lt;br /&gt;
|-&lt;br /&gt;
| 197 || [S1] [10.0.0+] [[#GetButtonConfigRegisteredSettingsEmbedded]]&lt;br /&gt;
|-&lt;br /&gt;
| 198 || [S1] [10.0.0+] [[#SetButtonConfigRegisteredSettingsEmbedded]]&lt;br /&gt;
|-&lt;br /&gt;
| 199 || [S1] [10.0.0+] [[#GetButtonConfigRegisteredSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [S1] [10.0.0+] [[#SetButtonConfigRegisteredSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [10.1.0+] [[#GetFieldTestingFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [10.1.0+] [[#SetFieldTestingFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [11.0.0+] GetPanelCrcMode&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [11.0.0+] SetPanelCrcMode&lt;br /&gt;
|-&lt;br /&gt;
| 205 || [S1] [13.0.0+] GetNxControllerSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 206 || [S1] [13.0.0+] SetNxControllerSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 207 || [S1] [14.0.0+] GetHearingProtectionSafeguardFlag&lt;br /&gt;
|-&lt;br /&gt;
| 208 || [S1] [14.0.0+] SetHearingProtectionSafeguardFlag&lt;br /&gt;
|-&lt;br /&gt;
| 209 || [S1] [14.0.0+] GetHearingProtectionSafeguardRemainingTime&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [S1] [14.0.0+] SetHearingProtectionSafeguardRemainingTime&lt;br /&gt;
|-&lt;br /&gt;
| 211 || [S2] GetWirelessCertificationHtmlFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 212 || [S2] GetWirelessCertificationHtmlFile&lt;br /&gt;
|-&lt;br /&gt;
| 213 || [S2] GetWirelessCertificationJpegFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 214 || [S2] GetWirelessCertificationJpegFile&lt;br /&gt;
|-&lt;br /&gt;
| 215 || [S2] GetHighContrastFlag&lt;br /&gt;
|-&lt;br /&gt;
| 216 || [S2] SetHighContrastFlag&lt;br /&gt;
|-&lt;br /&gt;
| 217 || [S2] GetTextToSpeechFlag&lt;br /&gt;
|-&lt;br /&gt;
| 218 || [S2] SetTextToSpeechFlag&lt;br /&gt;
|-&lt;br /&gt;
| 219 || [S2] [[#GetTextMagnificationRatio]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [S2] SetTextMagnificationRatio&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [17.0.0+] GetForceMonauralOutputFlag&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [17.0.0+] SetForceMonauralOutputFlag&lt;br /&gt;
|-&lt;br /&gt;
| 223 || [S2] GetUsbAudioVolumeSettings&lt;br /&gt;
|-&lt;br /&gt;
| 224 || [S2] SetUsbAudioVolumeSettings&lt;br /&gt;
|-&lt;br /&gt;
| 225 || [S2] GetTitleIconKeepFlag&lt;br /&gt;
|-&lt;br /&gt;
| 226 || [S2] SetTitleIconKeepFlag&lt;br /&gt;
|-&lt;br /&gt;
| 227 || [S2] GetBoldTextFlag&lt;br /&gt;
|-&lt;br /&gt;
| 228 || [S2] SetBoldTextFlag&lt;br /&gt;
|-&lt;br /&gt;
| 229 || [S2] GetSpeechToTextFlag&lt;br /&gt;
|-&lt;br /&gt;
| 230 || [S2] SetSpeechToTextFlag&lt;br /&gt;
|-&lt;br /&gt;
| 235 || [S2] GetColorFilterType&lt;br /&gt;
|-&lt;br /&gt;
| 236 || [S2] SetColorFilterType&lt;br /&gt;
|-&lt;br /&gt;
| 237 || [S2] GetPrioritizedOutputAudioDeviceSettings&lt;br /&gt;
|-&lt;br /&gt;
| 238 || [S2] SetPrioritizedOutputAudioDeviceSettings&lt;br /&gt;
|-&lt;br /&gt;
| 239 || [S2] GetPrioritizedInputAudioDeviceSettings&lt;br /&gt;
|-&lt;br /&gt;
| 240 || [S2] SetPrioritizedInputAudioDeviceSettings&lt;br /&gt;
|-&lt;br /&gt;
| 241 || [S2] GetTextToSpeechVoiceTypeForUi&lt;br /&gt;
|-&lt;br /&gt;
| 242 || [S2] SetTextToSpeechVoiceTypeForUi&lt;br /&gt;
|-&lt;br /&gt;
| 243 || [S2] GetLcdFlags&lt;br /&gt;
|-&lt;br /&gt;
| 244 || [S2] SetLcdFlags&lt;br /&gt;
|-&lt;br /&gt;
| 245 || [S2] GetTvHdrSettings&lt;br /&gt;
|-&lt;br /&gt;
| 246 || [S2] SetTvHdrSettings&lt;br /&gt;
|-&lt;br /&gt;
| 247 || [S2] IsColorInversionEnabled&lt;br /&gt;
|-&lt;br /&gt;
| 248 || [S2] SetColorInversionEnabled&lt;br /&gt;
|-&lt;br /&gt;
| 249 || [S2] GetKeyRemapEnableFlagOnQuickSettings&lt;br /&gt;
|-&lt;br /&gt;
| 250 || [S2] SetKeyRemapEnableFlagOnQuickSettings&lt;br /&gt;
|-&lt;br /&gt;
| 251 || [18.0.0+] GetAccountIdentificationSettings&lt;br /&gt;
|-&lt;br /&gt;
| 252 || [18.0.0+] SetAccountIdentificationSettings&lt;br /&gt;
|-&lt;br /&gt;
| 253 || [S2] GetDeviceLockPinCodeLength&lt;br /&gt;
|-&lt;br /&gt;
| 254 || [S2] GetDeviceLockPinCode&lt;br /&gt;
|-&lt;br /&gt;
| 255 || [S2] SetDeviceLockPinCode&lt;br /&gt;
|-&lt;br /&gt;
| 256 || [S2] GetDeviceLockEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 257 || [S2] GetDeviceLockStartPenaltyTime&lt;br /&gt;
|-&lt;br /&gt;
| 258 || [S2] SetDeviceLockStartPenaltyTime&lt;br /&gt;
|-&lt;br /&gt;
| 259 || [S2] GetDeviceLockErrorCount&lt;br /&gt;
|-&lt;br /&gt;
| 260 || [S2] SetDeviceLockErrorCount&lt;br /&gt;
|-&lt;br /&gt;
| 261 || [S2] GetBatteryCareModeEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 262 || [S2] SetBatteryCareModeEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 263 || [20.0.0+] AcquireVphymDirtyFlagEventHandle&lt;br /&gt;
|-&lt;br /&gt;
| 264 || [20.0.0+] GetVphymDirtyFlags&lt;br /&gt;
|-&lt;br /&gt;
| 265 || [S2] GetInitialLaunchSettings&lt;br /&gt;
|-&lt;br /&gt;
| 266 || [S2] SetInitialLaunchSettings&lt;br /&gt;
|-&lt;br /&gt;
| 267 || [S2] GetManufacturingTimeStamp&lt;br /&gt;
|-&lt;br /&gt;
| 268 || [S2] SetManufacturingTimeStamp&lt;br /&gt;
|-&lt;br /&gt;
| 269 || [S2] GetInputNoiseReductionForCommunicationFlag&lt;br /&gt;
|-&lt;br /&gt;
| 270 || [S2] SetInputNoiseReductionForCommunicationFlag&lt;br /&gt;
|-&lt;br /&gt;
| 271 || [S2] GetChatTranscriptionSettings&lt;br /&gt;
|-&lt;br /&gt;
| 272 || [S2] SetChatTranscriptionSettings&lt;br /&gt;
|-&lt;br /&gt;
| 273 || [S2] GetBuiltInMicrophoneGain&lt;br /&gt;
|-&lt;br /&gt;
| 274 || [S2] SetBuiltInMicrophoneGain&lt;br /&gt;
|-&lt;br /&gt;
| 275 || [S2] GetBuiltInMicrophoneJackGain&lt;br /&gt;
|-&lt;br /&gt;
| 276 || [S2] SetBuiltInMicrophoneJackGain&lt;br /&gt;
|-&lt;br /&gt;
| 277 || [S2] GetUsbAudioInputDeviceGainSettings&lt;br /&gt;
|-&lt;br /&gt;
| 278 || [S2] SetUsbAudioInputDeviceGainSettings&lt;br /&gt;
|-&lt;br /&gt;
| 279 || [S2] SetBluetoothStackFlag&lt;br /&gt;
|-&lt;br /&gt;
| 280 || [S2] SetHidDebugOcdUsbFlag&lt;br /&gt;
|-&lt;br /&gt;
| 281 || [S2] SetHidDebugRailFlag&lt;br /&gt;
|-&lt;br /&gt;
| 282 || [20.0.0+] [[#ConvertToProductModel|ConvertToProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 283 || [20.0.0+] [[#ConvertToProductModelName|ConvertToProductModelName]]&lt;br /&gt;
|-&lt;br /&gt;
| 284 || [S2] GetSaveDataPurgedForRepairFlag&lt;br /&gt;
|-&lt;br /&gt;
| 285 || [S2] SetSaveDataPurgedForRepairFlag&lt;br /&gt;
|-&lt;br /&gt;
| 286 || [S2] [20.0.0+] GetAppletParameterSet&lt;br /&gt;
|-&lt;br /&gt;
| 287 || [S2] [20.0.0+] SetAppletParameterSet&lt;br /&gt;
|-&lt;br /&gt;
| 288 || [S2] [20.0.0+] BindChatTranscriptionSettingsChangedEvent&lt;br /&gt;
|-&lt;br /&gt;
| 289 || [20.0.0+] GetDefaultAccountIdentificationFlagSet&lt;br /&gt;
|-&lt;br /&gt;
| 290 || [S2] [20.0.0+] GetMouseEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 291 || [S2] [20.0.0+] SetMouseEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 292 || [S2] [20.0.0+] GetTextToSpeechVoiceVolume&lt;br /&gt;
|-&lt;br /&gt;
| 293 || [S2] [20.0.0+] SetTextToSpeechVoiceVolume&lt;br /&gt;
|-&lt;br /&gt;
| 294 || [S2] [20.0.0+] GetTextToSpeechVoiceSpeed&lt;br /&gt;
|-&lt;br /&gt;
| 295 || [S2] [20.0.0+] SetTextToSpeechVoiceSpeed&lt;br /&gt;
|-&lt;br /&gt;
| 296 || [S2] [20.0.0+] GetSleepSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 297 || [S2] [20.0.0+] SetSleepSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 298 || [S2] [20.0.0+] GetMousePointerSpeedScale&lt;br /&gt;
|-&lt;br /&gt;
| 299 || [S2] [20.0.0+] SetMousePointerSpeedScale&lt;br /&gt;
|-&lt;br /&gt;
| 300 || [20.0.0+] AcquirePushNotificationDirtyFlagEventHandle&lt;br /&gt;
|-&lt;br /&gt;
| 301 || [20.0.0+] GetPushNotificationDirtyFlags&lt;br /&gt;
|-&lt;br /&gt;
| 302 || [S2] [20.0.0+] GetTvHdrSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 303 || [S2] [20.0.0+] SetTvHdrSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [S2] [20.0.0+] GetOunceProControllerMicrophoneJackGain&lt;br /&gt;
|-&lt;br /&gt;
| 305 || [S2] [20.0.0+] SetOunceProControllerMicrophoneJackGain&lt;br /&gt;
|-&lt;br /&gt;
| 306 || [20.0.0+] GetPinCodeReregistrationGuideAccounts&lt;br /&gt;
|-&lt;br /&gt;
| 307 || [20.0.0+] SetPinCodeReregistrationGuideAccounts&lt;br /&gt;
|-&lt;br /&gt;
| 308 || [S2] [20.0.0+] GetChatTranscriptionSettings&lt;br /&gt;
|-&lt;br /&gt;
| 309 || [S2] [20.0.0+] SetChatTranscriptionSettings&lt;br /&gt;
|-&lt;br /&gt;
| 310 || [S2] [20.0.0+] GetDeviceLockPinCodeLsbParity&lt;br /&gt;
|-&lt;br /&gt;
| 311 || [S2] [20.0.0+] VerifyDeviceLockPinCode&lt;br /&gt;
|-&lt;br /&gt;
| 312 || [S2] [20.0.0+] GetDeviceLockVeificationForbiddenFlag&lt;br /&gt;
|-&lt;br /&gt;
| 315 || [21.0.0+] GetHttpAuthConfigs&lt;br /&gt;
|-&lt;br /&gt;
| 319 || [21.0.0+] GetAccountUserSettings&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [21.0.0+] SetAccountUserSettings&lt;br /&gt;
|-&lt;br /&gt;
| 321 || [21.0.0+] GetDefaultAccountUserSettings&lt;br /&gt;
|-&lt;br /&gt;
| 324 || [22.0.0+] GetPtmQhClearCount&lt;br /&gt;
|-&lt;br /&gt;
| 325 || [22.0.0+] SetPtmQhClearCount&lt;br /&gt;
|-&lt;br /&gt;
| 326 || [22.0.0+] GetAirPlaneModeRestoreFlagSet&lt;br /&gt;
|-&lt;br /&gt;
| 327 || [22.0.0+] SetAirPlaneModeRestoreFlagSet&lt;br /&gt;
|-&lt;br /&gt;
| 328 || [22.0.0+] DeleteSettingsPerAccount&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Official user-processes gets a new service session handle each time a set:sys cmd is used, with the session being closed afterwards.&lt;br /&gt;
&lt;br /&gt;
== SetLanguageCode ==&lt;br /&gt;
Takes an input [[#LanguageCode]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetFirmwareVersion ==&lt;br /&gt;
Takes a type-0x1A output buffer. User-processes use hard-coded size 0x100.&lt;br /&gt;
&lt;br /&gt;
This was removed with S2.&lt;br /&gt;
&lt;br /&gt;
If needed, reads the content of the [[System_Version_Title]] &amp;quot;/file&amp;quot; into state. This is only done once.&lt;br /&gt;
&lt;br /&gt;
Then the above 0x100-byte data is copied to the output buffer.&lt;br /&gt;
&lt;br /&gt;
== GetAccountSettings ==&lt;br /&gt;
No input, returns an output [[#AccountSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetAccountSettings ==&lt;br /&gt;
Takes an input [[#AccountSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetEulaVersions ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#EulaVersion]], returns an output s32 total_out.&lt;br /&gt;
&lt;br /&gt;
== SetEulaVersions ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#EulaVersion]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetColorSetId ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
This is the current Theme set by System Settings.&lt;br /&gt;
&lt;br /&gt;
* 0: &amp;quot;Basic White&amp;quot;&lt;br /&gt;
* 1: &amp;quot;Basic Black&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== SetColorSetId ==&lt;br /&gt;
Takes an input s32, no output.&lt;br /&gt;
&lt;br /&gt;
== GetNotificationSettings ==&lt;br /&gt;
No input, returns an output [[#NotificationSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetNotificationSettings ==&lt;br /&gt;
Takes an input [[#NotificationSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetAccountNotificationSettings ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#AccountNotificationSettings]], returns an output s32 total_out.&lt;br /&gt;
&lt;br /&gt;
== SetAccountNotificationSettings ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#AccountNotificationSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetSettingsItemValue ==&lt;br /&gt;
Takes two type-0x19 input buffers and a type-0x6 output buffer. Returns an output u64 for the actual size written to the outbuf.&lt;br /&gt;
&lt;br /&gt;
The outbuf_size is compared with the config_size. When config_size is larger than outbuf_size, outbuf_size is used for the memcpy, otherwise config_size is used. Afterwards the size used for the memcpy is written to output(see above).&lt;br /&gt;
&lt;br /&gt;
If loading from main config fails, it will also attempt to load config from various state if the input strings match hard-coded strings.&lt;br /&gt;
&lt;br /&gt;
== GetTvSettings ==&lt;br /&gt;
No input, returns an output [[#TvSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetTvSettings ==&lt;br /&gt;
Takes an input [[#TvSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetDebugModeFlag ==&lt;br /&gt;
Returns an output u8.&lt;br /&gt;
&lt;br /&gt;
Loads the 1-byte config for &amp;lt;&amp;quot;settings_debug&amp;quot;, &amp;quot;is_debug_mode_enabled&amp;quot;&amp;gt;. If that fails, value 0x1 is written to output. This uses the same func as ReadSetting internally.&lt;br /&gt;
&lt;br /&gt;
Returned retval is always 0.&lt;br /&gt;
&lt;br /&gt;
== GetPrimaryAlbumStorage ==&lt;br /&gt;
No input, returns an output s32 [[#PrimaryAlbumStorage]].&lt;br /&gt;
&lt;br /&gt;
== SetPrimaryAlbumStorage ==&lt;br /&gt;
Takes an input s32 [[#PrimaryAlbumStorage]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetBatteryLot ==&lt;br /&gt;
No input, returns an output [[#BatteryLot]].&lt;br /&gt;
&lt;br /&gt;
== GetSerialNumber ==&lt;br /&gt;
Returns the 0x18-byte SerialNumber string.&lt;br /&gt;
&lt;br /&gt;
== GetSleepSettings ==&lt;br /&gt;
No input, returns an output [[#SleepSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetSleepSettings ==&lt;br /&gt;
Takes an input [[#SleepSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetInitialLaunchSettings ==&lt;br /&gt;
No input, returns an output [[#InitialLaunchSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetInitialLaunchSettings ==&lt;br /&gt;
Takes an input [[#InitialLaunchSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetDeviceNickName ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#DeviceNickName]].&lt;br /&gt;
&lt;br /&gt;
With [10.1.0+] sdknso now uses the set cmd instead of the setsys cmd.&lt;br /&gt;
&lt;br /&gt;
== SetDeviceNickName ==&lt;br /&gt;
Takes a type-0x15 input buffer containing a [[#DeviceNickName]].&lt;br /&gt;
&lt;br /&gt;
== GetProductModel ==&lt;br /&gt;
No input, returns an output s32 [[#ProductModel|ProductModel]].&lt;br /&gt;
&lt;br /&gt;
== GetMiiAuthorId ==&lt;br /&gt;
No input, returns an output &amp;quot;nn::util::Uuid&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== GetServiceDiscoveryControlSettings ==&lt;br /&gt;
Returns an u32 [[#ServiceDiscoveryControlSettings|ServiceDiscoveryControlSettings]].&lt;br /&gt;
&lt;br /&gt;
== GetErrorReportSharePermission ==&lt;br /&gt;
No input, returns an output s32 [[#ErrorReportSharePermission]].&lt;br /&gt;
&lt;br /&gt;
== SetErrorReportSharePermission ==&lt;br /&gt;
Takes an input s32 [[#ErrorReportSharePermission]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetAppletLaunchFlags ==&lt;br /&gt;
No input, returns an u32 bitmask [[#AppletLaunchFlag]].&lt;br /&gt;
&lt;br /&gt;
== SetAppletLaunchFlags ==&lt;br /&gt;
Takes an input u32 bitmask [[#AppletLaunchFlag]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetKeyboardLayout ==&lt;br /&gt;
No input, returns an output s32 [[#KeyboardLayout]].&lt;br /&gt;
&lt;br /&gt;
== SetKeyboardLayout ==&lt;br /&gt;
Takes an input s32 [[#KeyboardLayout]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetAllowedSslHosts ==&lt;br /&gt;
Takes a type-0x6 output buffer. Returns an output s32 entry count.&lt;br /&gt;
&lt;br /&gt;
== GetRebootlessSystemUpdateVersion ==&lt;br /&gt;
No input, returns an output [[#RebootlessSystemUpdateVersion]].&lt;br /&gt;
&lt;br /&gt;
== GetQuestFlag ==&lt;br /&gt;
Gets a flag determining whether the console is a kiosk unit (codenamed &amp;quot;Quest&amp;quot;). Used by qlaunch to determine whether to launch Retail Interactive Display Menu.&lt;br /&gt;
&lt;br /&gt;
== GetDataDeletionSettings ==&lt;br /&gt;
No input, returns an output [[#DataDeletionSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetDataDeletionSettings ==&lt;br /&gt;
Takes an input [[#DataDeletionSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetWirelessCertificationFileSize ==&lt;br /&gt;
No input, returns an output u64 size.&lt;br /&gt;
&lt;br /&gt;
== GetWirelessCertificationFile ==&lt;br /&gt;
Takes a type-0x6 output buffer, returns an output u64 size.&lt;br /&gt;
&lt;br /&gt;
This gets the [[Flash_Filesystem#PRODINFOF|WirelessCertificationFile]].&lt;br /&gt;
&lt;br /&gt;
== SetRegionCode ==&lt;br /&gt;
Takes an input s32 [[#RegionCode_2|RegionCode]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetChineseTraditionalInputMethod ==&lt;br /&gt;
No input, returns an output s32 [[#ChineseTraditionalInputMethod]].&lt;br /&gt;
&lt;br /&gt;
== SetChineseTraditionalInputMethod ==&lt;br /&gt;
Takes an input s32 [[#ChineseTraditionalInputMethod]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetHomeMenuScheme ==&lt;br /&gt;
No input. Returns an output [[#HomeMenuScheme]].&lt;br /&gt;
&lt;br /&gt;
The colors are loaded from [[Calibration]], with the set of fields to use selected by [[Calibration#ColorVariation|ColorVariation]].&lt;br /&gt;
&lt;br /&gt;
== GetT ==&lt;br /&gt;
No input, returns an output u8 bool &#039;&#039;&#039;IsT&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[9.0.0+] This is a wrapper for [[#GetPlatformRegion]]: &amp;lt;code&amp;gt;IsT = (PlatformRegion == 2)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== SetT ==&lt;br /&gt;
Takes an input u8 bool &#039;&#039;&#039;IsT&#039;&#039;&#039;, no output.&lt;br /&gt;
&lt;br /&gt;
[9.0.0+] This is a wrapper for [[#SetPlatformRegion]]: &amp;lt;code&amp;gt;PlatformRegion = 1 + (IsT &amp;amp; 1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== GetPlatformRegion ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetPlatformRegion ==&lt;br /&gt;
Takes an input s32, no output.&lt;br /&gt;
&lt;br /&gt;
== GetHomeMenuSchemeModel ==&lt;br /&gt;
No input. Returns an output u32.&lt;br /&gt;
&lt;br /&gt;
Loads the 0xB-byte setting &amp;lt;&amp;quot;settings_debug&amp;quot;, &amp;quot;home_menu_scheme_model&amp;quot;&amp;gt;, throwing an error if loading this fails. Depending on the content of the setting, the output u32 is either determined by the value of this setting, or loaded from [[Calibration#ColorModel|ColorModel]].&lt;br /&gt;
&lt;br /&gt;
== GetMemoryUsageRateFlag ==&lt;br /&gt;
No input, returns an output u8 bool.&lt;br /&gt;
&lt;br /&gt;
== GetTouchScreenMode ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
Official sw loads the output as an u8 and copies it to an output [[#TouchScreenMode]].&lt;br /&gt;
&lt;br /&gt;
== SetTouchScreenMode ==&lt;br /&gt;
Takes an input s32, no output.&lt;br /&gt;
&lt;br /&gt;
Official sw sets the input to an u8 loaded from an input [[#TouchScreenMode]].&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigSettingsFull ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigSettingsFull ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigSettingsEmbedded ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigSettingsEmbedded ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigSettingsLeft ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigSettingsLeft ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigSettingsRight ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigSettingsRight ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigRegisteredSettingsEmbedded ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#ButtonConfigRegisteredSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigRegisteredSettingsEmbedded ==&lt;br /&gt;
Takes a type-0x15 input buffer containing a [[#ButtonConfigRegisteredSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigRegisteredSettings ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigRegisteredSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigRegisteredSettings ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigRegisteredSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetFieldTestingFlag ==&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
== SetFieldTestingFlag ==&lt;br /&gt;
Takes an input bool, no output.&lt;br /&gt;
&lt;br /&gt;
== GetTextMagnificationRatio ==&lt;br /&gt;
This is exclusive to S2.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output float.&lt;br /&gt;
&lt;br /&gt;
== ConvertToProductModel ==&lt;br /&gt;
Takes an input [[#ProductModelName|ProductModelName]], returns an output [[#ProductModel|ProductModel]].&lt;br /&gt;
&lt;br /&gt;
== ConvertToProductModelName ==&lt;br /&gt;
Takes an input [[#ProductModel|ProductModel]], return an output [[#ProductModelName|ProductModelName]].&lt;br /&gt;
&lt;br /&gt;
When the input [[#ProductModel|ProductModel]] is invalid, this writes 0 to output and returns 0.&lt;br /&gt;
&lt;br /&gt;
= Language =&lt;br /&gt;
This is &amp;quot;nn::settings::Language&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Japanese&lt;br /&gt;
|-&lt;br /&gt;
| 1 || AmericanEnglish&lt;br /&gt;
|-&lt;br /&gt;
| 2 || French&lt;br /&gt;
|-&lt;br /&gt;
| 3 || German&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Italian&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Spanish&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Chinese&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Korean&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Dutch&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Portuguese&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Russian&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Taiwanese&lt;br /&gt;
|-&lt;br /&gt;
| 12 || BritishEnglish&lt;br /&gt;
|-&lt;br /&gt;
| 13 || CanadianFrench&lt;br /&gt;
|-&lt;br /&gt;
| 14 || LatinAmericanSpanish&lt;br /&gt;
|-&lt;br /&gt;
| 15 || [4.0.0+] SimplifiedChinese&lt;br /&gt;
|-&lt;br /&gt;
| 16 || [4.0.0+] TraditionalChinese&lt;br /&gt;
|-&lt;br /&gt;
| 17 || [10.1.0+] BrazilianPortuguese&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= LanguageCode =&lt;br /&gt;
This is &amp;quot;nn::settings::LanguageCode&amp;quot;. This is an u64, which is a NUL-terminated string.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || [[#Language]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ja&amp;quot; || Japanese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;en-US&amp;quot; || AmericanEnglish&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;fr&amp;quot; || French&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;de&amp;quot; || German&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;it&amp;quot; || Italian&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;es&amp;quot; || Spanish&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;zh-CN&amp;quot; || Chinese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ko&amp;quot; || Korean&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;nl&amp;quot; || Dutch&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;pt&amp;quot; || Portuguese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ru&amp;quot; || Russian&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;zh-TW&amp;quot; || Taiwanese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;en-GB&amp;quot; || BritishEnglish&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;fr-CA&amp;quot; || CanadianFrench&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;es-419&amp;quot; || LatinAmericanSpanish&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;zh-Hans&amp;quot; || [4.0.0+] SimplifiedChinese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;zh-Hant&amp;quot; || [4.0.0+] TraditionalChinese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;pt-BR&amp;quot; || [10.1.0+] BrazilianPortuguese&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AccelerometerOffset =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AccelerometerOffset&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || X&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || Z&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AccelerometerScale =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AccelerometerScale&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || X&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || Z&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcdsaCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcdsaCertificate&amp;quot;. This is a 0x70-byte struct.&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcqvBlsCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcqvBlsCertificate&amp;quot;. This is a 0x20-byte struct.&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcqvBlsKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcqvBlsKey&amp;quot;. This is a 0x40-byte struct.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x40 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x40 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcqvBlsRootCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcqvBlsRootCertificate&amp;quot;. This is a 0x90-byte struct.&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcqvCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcqvCertificate&amp;quot;. This is a 0x14-byte struct.&lt;br /&gt;
&lt;br /&gt;
= AmiiboKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboKey&amp;quot;. This is a 0x50-byte struct.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x50 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AnalogStickFactoryCalibration =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AnalogStickFactoryCalibration&amp;quot;. Same as [[Calibration#AnalogStickFactoryCalibration|AnalogStickFactoryCalibration]].&lt;br /&gt;
&lt;br /&gt;
= AnalogStickModelParameter =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AnalogStickModelParameter&amp;quot;. Same as [[Calibration#AnalogStickModelParameter|AnalogStickModelParameter]].&lt;br /&gt;
&lt;br /&gt;
= BatteryLot =&lt;br /&gt;
This is &amp;quot;nn::settings::BatteryLot&amp;quot;. This is a 0x18-byte struct.&lt;br /&gt;
&lt;br /&gt;
= BdAddress =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::BdAddress&amp;quot;. This is a 0x6-byte struct.&lt;br /&gt;
&lt;br /&gt;
= ConfigurationId1 =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::ConfigurationId1&amp;quot;. This is a 0x1E-byte struct.&lt;br /&gt;
&lt;br /&gt;
Usually, this is a string with the following format:&lt;br /&gt;
  {EventType}_{ProductModelType}_{MajorVersion}_{MinorVersion}_{MicroVersion}&lt;br /&gt;
&lt;br /&gt;
== EventType ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;FP&amp;quot; || Functional prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;EP&amp;quot; || Engineering prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;DP&amp;quot; || Design prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;DPRD&amp;quot; || Design prototype for R&amp;amp;D&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HOAG&amp;quot; || Hoag prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;COPPER&amp;quot; || Copper prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;EDEV&amp;quot; || Extcon development kit for Icosa and Iowa&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;SDEV&amp;quot; || SPI development kit for Icosa and Iowa&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;MEDEV&amp;quot; || Mariko EDEV (deprecated)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;MSDEV&amp;quot; || Mariko SDEV (deprecated)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HDEV&amp;quot; || Development kit for Hoag&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ADEV&amp;quot; || Development kit for Aula&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;MP&amp;quot; || Mass production (retail Icosa)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;MNX&amp;quot; || Mariko NX (retail Iowa)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HNX&amp;quot; || Hoag NX (retail Hoag)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ANX&amp;quot; || Aula NX (retail Aula)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ProductModelType ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;00&amp;quot; || Icosa&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;01&amp;quot; || Iowa (previously Copper)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;02&amp;quot; || Hoag&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;03&amp;quot; || Calcio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;04&amp;quot; || Aula&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ConsoleSixAxisSensorHorizontalOffset =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::ConsoleSixAxisSensorHorizontalOffset&amp;quot;. Same as [[Calibration#ConsoleSixAxisSensorHorizontalOffset|ConsoleSixAxisSensorHorizontalOffset]].&lt;br /&gt;
&lt;br /&gt;
= CountryCode =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::CountryCode&amp;quot;. This is a 0x3-byte struct.&lt;br /&gt;
&lt;br /&gt;
= EccB233DeviceCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::EccB233DeviceCertificate&amp;quot;. This is a 0x180-byte struct.&lt;br /&gt;
&lt;br /&gt;
= EccB233DeviceKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::EccB233DeviceKey&amp;quot;. This is a 0x30-byte struct or a 0x54-byte struct in the extended version.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x54 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= GameCardCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::GameCardCertificate&amp;quot;. This is a 0x400-byte struct.&lt;br /&gt;
&lt;br /&gt;
= GameCardKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::GameCardKey&amp;quot;. This is a 0x110-byte struct or a 0x130-byte struct in the extended version.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x130 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= GyroscopeOffset =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::GyroscopeOffset&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || X&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || Z&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= GyroscopeScale =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::GyroscopeScale&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || X&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || Z&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= MacAddress =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::MacAddress&amp;quot;. This is a 0x6-byte struct.&lt;br /&gt;
&lt;br /&gt;
= Rsa2048DeviceCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::Rsa2048DeviceCertificate&amp;quot;. This is a 0x240-byte struct.&lt;br /&gt;
&lt;br /&gt;
= Rsa2048DeviceKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::Rsa2048DeviceKey&amp;quot;. This is a 0x220-byte struct or a 0x240-byte struct in the extended version.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x240 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x240 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SerialNumber =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::SerialNumber&amp;quot;. This is a 0x18-byte struct.&lt;br /&gt;
&lt;br /&gt;
= SpeakerParameter =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::SpeakerParameter&amp;quot;. This is copied from the first 0x5A bytes of [[Calibration#SpeakerCalibrationValue|SpeakerCalibrationValue]].&lt;br /&gt;
&lt;br /&gt;
= SslCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::SslCertificate&amp;quot;. This is a 0x804-byte struct.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || Variable || Data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SslKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::SslKey&amp;quot;. This is a 0x110-byte struct or a 0x130-byte struct in the extended version.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x130 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= RegionCode =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::RegionCode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Japan&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Usa&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Europe&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Australia&lt;br /&gt;
|-&lt;br /&gt;
| 4 || China&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Korea&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Taiwan&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AudioOutputMode =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AudioOutputMode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1ch&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2ch&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 5_1ch&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 7_1ch&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AudioOutputModeTarget =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AudioOutputModeTarget&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Hdmi&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Speaker&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Headphone&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AudioVolumeTarget =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AudioVolumeTarget&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Speaker&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Headphone&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= DeviceNickName =&lt;br /&gt;
This is &amp;quot;nn::settings::system::DeviceNickName&amp;quot;. This is a 0x80-byte struct.&lt;br /&gt;
&lt;br /&gt;
= Edid =&lt;br /&gt;
This is &amp;quot;nn::settings::system::Edid&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x80 || Data0&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || 0x80 || Data1&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x80 || [13.0.0+] Data2&lt;br /&gt;
|-&lt;br /&gt;
| 0x180 || 0x80 || [13.0.0+] Data3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= RegionCode =&lt;br /&gt;
This is &amp;quot;nn::settings::system::RegionCode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Japan&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Usa&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Europe&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Australia&lt;br /&gt;
|-&lt;br /&gt;
| 4 || HongKongTaiwanKorea&lt;br /&gt;
|-&lt;br /&gt;
| 5 || China&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UserSelectorFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::UserSelectorFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || SkipsIfSingleUser&lt;br /&gt;
|-&lt;br /&gt;
| 31 || Unknown&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UserSelectorSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::UserSelectorSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This contains an u32 bitmask for [[#UserSelectorFlag]].&lt;br /&gt;
&lt;br /&gt;
= AccountSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AccountSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This contains [[#UserSelectorSettings]].&lt;br /&gt;
&lt;br /&gt;
= ClockSourceId =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ClockSourceId&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || NetworkSystemClock&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SteadyClock&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NotificationVolume =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NotificationVolume&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Mute&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Low&lt;br /&gt;
|-&lt;br /&gt;
| 2 || High&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= FriendPresenceOverlayPermission =&lt;br /&gt;
This is &amp;quot;nn::settings::system::FriendPresenceOverlayPermission&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || NotConfirmed&lt;br /&gt;
|-&lt;br /&gt;
| 1 || NoDisplay&lt;br /&gt;
|-&lt;br /&gt;
| 2 || FavoriteFriends&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Friends&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= TvResolution =&lt;br /&gt;
This is &amp;quot;nn::settings::system::TvResolution&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Auto&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 1080p&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 720p&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 480p&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= HdmiContentType =&lt;br /&gt;
This is &amp;quot;nn::settings::system::HdmiContentType&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || None&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Graphics&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Cinema&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Photo&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Game&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= RgbRange =&lt;br /&gt;
This is &amp;quot;nn::settings::system::RgbRange&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Auto&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Full&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Limited&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= CmuMode =&lt;br /&gt;
This is &amp;quot;nn::settings::system::CmuMode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || None&lt;br /&gt;
|-&lt;br /&gt;
| 1 || ColorInvert&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HighContrast&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GrayScale&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= HandheldSleepPlan =&lt;br /&gt;
This is &amp;quot;nn::settings::system::HandheldSleepPlan&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1Min&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 3Min&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 5Min&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 10Min&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 30Min&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Never&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ConsoleSleepPlan =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ConsoleSleepPlan&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1Hour&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2Hour&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 3Hour&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 6Hour&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 12Hour&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Never&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= EulaVersion =&lt;br /&gt;
This is &amp;quot;nn::settings::system::EulaVersion&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Version&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || [[#RegionCode_2|RegionCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || [[#SteadyClockSourceId|ClockType]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || [[Glue_services#PosixTime|NetworkSystemClock]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x18 || [[Glue_services#SteadyClockTimePoint|SteadyClock]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= FirmwareVersion =&lt;br /&gt;
This is &amp;quot;nn::settings::system::FirmwareVersion&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Major&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || Minor&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x1 || Micro&lt;br /&gt;
|-&lt;br /&gt;
| 0x3 || 0x1 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || ReleaseNumber&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Platform&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x40 || Revision&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x18 || DisplayVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || 0x80 || DisplayName&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= PtmFuelGaugeParameter =&lt;br /&gt;
This is &amp;quot;nn::settings::system::PtmFuelGaugeParameter&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || Rcomp0&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || TempCo&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || FullCap&lt;br /&gt;
|-&lt;br /&gt;
| 0x6 || 0x2 || FullCapNom&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x2 || IavgEmpty&lt;br /&gt;
|-&lt;br /&gt;
| 0xA || 0x2 || QrTable00&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x2 || QrTable10&lt;br /&gt;
|-&lt;br /&gt;
| 0xE || 0x2 || QrTable20&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x2 || QrTable30&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || 0x2 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 0x4 || Cycles&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SecuritySettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::SecuritySettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || AuthenticationMode&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || EncryptionMode&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x40 || KeyMaterial&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x4 || KeyMaterialLength&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NotificationTime =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NotificationTime&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Hour&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || Minute&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NotificationFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NotificationFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || RingtoneFlag&lt;br /&gt;
|-&lt;br /&gt;
| 1 || DownloadCompletionFlag&lt;br /&gt;
|-&lt;br /&gt;
| 8 || EnablesNews&lt;br /&gt;
|-&lt;br /&gt;
| 9 || IncomingLampFlag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NotificationSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NotificationSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#NotificationFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || [[#NotificationVolume|Volume]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || [[#NotificationTime|HeadTime]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || [[#NotificationTime|TailTime]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AccountNotificationFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AccountNotificationFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || FriendOnlineFlag&lt;br /&gt;
|-&lt;br /&gt;
| 1 || FriendRequestFlag&lt;br /&gt;
|-&lt;br /&gt;
| 8 || CoralInvitationFlag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AccountNotificationSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AccountNotificationSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || [[Account_services#Uid|Uid]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x4 || [[#AccountNotificationFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 0x1 || [[#FriendPresenceOverlayPermission|FriendPresenceOverlayPermission]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x15 || 0x1 || [[#FriendPresenceOverlayPermission|FriendInvitationOverlayPermission]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x16 || 0x2 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= TvFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::TvFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Allows4k&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Allows3d&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AllowsCec&lt;br /&gt;
|-&lt;br /&gt;
| 3 || PreventsScreenBurnIn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= TvSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::TvSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#TvFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || [[#TvResolution|TvResolution]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || [[#HdmiContentType|HdmiContentType]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || [[#RgbRange|RgbRange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x4 || [[#CmuMode|CmuMode]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 0x4 || TvUnderscan&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x4 || TvGamma&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x4 || ContrastRatio&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= DataDeletionFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::DataDeletionFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || AutomaticDeletionFlag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= DataDeletionSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::DataDeletionSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#DataDeletionFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || UseCount&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SleepFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::SleepFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || SleepsWhilePlayingMedia&lt;br /&gt;
|-&lt;br /&gt;
| 1 || WakesAtPowerStateChange&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SleepSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::SleepSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#SleepFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || [[#HandheldSleepPlan|HandheldSleepPlan]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || [[#ConsoleSleepPlan|ConsoleSleepPlan]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= InitialLaunchFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::InitialLaunchFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || InitialLaunchCompletionFlag&lt;br /&gt;
|-&lt;br /&gt;
| 8 || InitialLaunchUserAdditionFlag&lt;br /&gt;
|-&lt;br /&gt;
| 16 || InitialLaunchTimestampFlag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= InitialLaunchSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::InitialLaunchSettings&amp;quot;. This struct is 8-byte aligned.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#InitialLaunchFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x18 || [[Glue_services#SteadyClockTimePoint|TimeStamp]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= RebootlessSystemUpdateVersion =&lt;br /&gt;
This is &amp;quot;nn::settings::system::RebootlessSystemUpdateVersion&amp;quot;. This struct is 4-byte aligned.&lt;br /&gt;
&lt;br /&gt;
This is the content of the RebootlessSystemUpdateVersion SystemData, in the &amp;quot;/version&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Version&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x1C || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || DisplayVersion&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= PrimaryAlbumStorage =&lt;br /&gt;
This is &amp;quot;nn::settings::system::PrimaryAlbumStorage&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Nand&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SdCard&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ErrorReportSharePermission =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ErrorReportSharePermission&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || NotConfirmed&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Granted&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Denied&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ServiceDiscoveryControlSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ServiceDiscoveryControlSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| IsChangeEnvironmentIdentifierDisabled&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AppletLaunchFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AppletLaunchFlag&amp;quot;. This is an u32 bitmask.&lt;br /&gt;
&lt;br /&gt;
= KeyboardLayout =&lt;br /&gt;
This is &amp;quot;nn::settings::KeyboardLayout&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || EnglishUs&lt;br /&gt;
|-&lt;br /&gt;
| 2 || EnglishUsInternational&lt;br /&gt;
|-&lt;br /&gt;
| 3 || EnglishUk&lt;br /&gt;
|-&lt;br /&gt;
| 4 || French&lt;br /&gt;
|-&lt;br /&gt;
| 5 || FrenchCa&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Spanish&lt;br /&gt;
|-&lt;br /&gt;
| 7 || SpanishLatin&lt;br /&gt;
|-&lt;br /&gt;
| 8 || German&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Italian&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Portuguese&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Russian&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Korean&lt;br /&gt;
|-&lt;br /&gt;
| 13 || ChineseSimplified&lt;br /&gt;
|-&lt;br /&gt;
| 14 || ChineseTraditional&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ChineseTraditionalInputMethod =&lt;br /&gt;
This is &amp;quot;nn::settings::ChineseTraditionalInputMethod&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= HomeMenuScheme =&lt;br /&gt;
This is &amp;quot;nn::settings::system::HomeMenuScheme&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || MainColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || BackColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SubColor&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x4 || BezelColor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= TouchScreenMode =&lt;br /&gt;
This is &amp;quot;nn::settings::system::TouchScreenMode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Stylus&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Standard&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ButtonConfigSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ButtonConfigSettings&amp;quot;. This is a 0x5A8-byte struct.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || IsFull bool flag. 0 = empty config, 1 = config set. Also accessed as an u32, but only bit0 is used.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x3 || Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x1C4 || Unused&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C8 || 0x3E0 || Config&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ButtonConfigRegisteredSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ButtonConfigRegisteredSettings&amp;quot;. This is a 0x5C8-byte struct.&lt;br /&gt;
&lt;br /&gt;
= BluetoothDevicesSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::BluetoothDevicesSettings&amp;quot;. This is a 0x200-byte struct.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x6 || [[BTM_services#BdAddress|BdAddr]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x6 || 0x20 || [13.0.0+] Reserved ([1.0.0-12.1.0] [[BTM_services#BdName|DeviceName]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x26 || 0x3 || [[BTM_services#ClassOfDevice|ClassOfDevice]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x29 || 0x10 || LinkKey&lt;br /&gt;
|-&lt;br /&gt;
| 0x39 || 0x1 || LinkKeyPresent&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A || 0x2 || Version&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C || 0x4 || TrustedServices&lt;br /&gt;
|-&lt;br /&gt;
| 0x40 || 0x2 || Vid&lt;br /&gt;
|-&lt;br /&gt;
| 0x42 || 0x2 || Pid&lt;br /&gt;
|-&lt;br /&gt;
| 0x44 || 0x1 || SubClass&lt;br /&gt;
|-&lt;br /&gt;
| 0x45 || 0x1 || AttributeMask&lt;br /&gt;
|-&lt;br /&gt;
| 0x46 || 0x2 || DescriptorLength&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x80 || Descriptor&lt;br /&gt;
|-&lt;br /&gt;
| 0xC8 || 0x1 || KeyType&lt;br /&gt;
|-&lt;br /&gt;
| 0xC9 || 0x1 || DeviceType&lt;br /&gt;
|-&lt;br /&gt;
| 0xCA || 0x2 || BrrSize&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC || 0x9 || Brr&lt;br /&gt;
|-&lt;br /&gt;
| 0xD5 || 0x1 || [13.0.0+] AudioSourceVolume&lt;br /&gt;
|-&lt;br /&gt;
| 0xD6 || 0xF9 || [13.0.0+] DeviceName&lt;br /&gt;
|-&lt;br /&gt;
| 0x1CF || 0x1 || [15.0.0+] AudioSinkVolume&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D0 || 0x4 || [14.0.0+] AudioFlags&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D4 || 0x2C || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NxControllerLegacySettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NxControllerLegacySettings&amp;quot; ([1.0.0-12.1.0] &amp;quot;nn::settings::system::NxControllerSettings&amp;quot;). This is a 0x29-byte struct.&lt;br /&gt;
&lt;br /&gt;
= NxControllerSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NxControllerSettings&amp;quot;. This is a 0x42C-byte struct. This was added with [13.0.0+].&lt;br /&gt;
&lt;br /&gt;
= ProductModel =&lt;br /&gt;
Ths is &amp;quot;nn::settings::system::ProductModel&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Range 1-6 is Nintendo Switch, range 7-12 is Nintendo Switch 2.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! [[#ProductModelName|ProductModelName]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || &amp;quot;HAC&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 3 || &amp;quot;HAD&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 4 || &amp;quot;HDH&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 6 || &amp;quot;HEG&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 7 || &amp;quot;BEE&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ProductModelName =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ProductModelName&amp;quot;. This is a 0x8-byte struct containing a [[#ProductModel|string]].&lt;br /&gt;
&lt;br /&gt;
= System Configuration =&lt;br /&gt;
There&#039;s a common configuration title (*818), and one configuration title for each [[SMC#HardwareType|HardwareType]].&lt;br /&gt;
&lt;br /&gt;
See [[System_Settings]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14636</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14636"/>
		<updated>2026-04-30T17:10:25Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+] [[#GetClientProductModel|GetClientProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== GetClientProductModel ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from the [[Settings_services#ProductModel|ProductModel]] field in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#SendClientProfile|SendClientProfile]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends [[#RequestServerProfile|RequestServerProfile]], then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: &amp;lt;code&amp;gt;(Major&amp;lt;&amp;lt;16) | (Minor&amp;lt;&amp;lt;8) | Micro&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Settings_services&amp;diff=14635</id>
		<title>Settings services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Settings_services&amp;diff=14635"/>
		<updated>2026-04-30T16:39:30Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= set =&lt;br /&gt;
This is &amp;quot;nn::settings::ISettingsServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetLanguageCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetAvailableLanguageCodes]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [4.0.0+] [[#MakeLanguageCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#GetAvailableLanguageCodeCount]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#GetRegionCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [4.0.0+] [[#GetAvailableLanguageCodes2]]&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [4.0.0+] [[#GetAvailableLanguageCodeCount2]]&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [4.0.0+] [[#GetKeyCodeMap]]&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [5.0.0+] [[#GetQuestFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 9 || [6.0.0+] [[#GetKeyCodeMap2]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [9.0.0+] [[#GetFirmwareVersionForDebug]]&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [10.1.0+] [[#GetDeviceNickName]]&lt;br /&gt;
|-&lt;br /&gt;
| 12 || [18.0.0+] GetKeyCodeMapByPort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[4.0.0+] Official user-processes now use GetAvailableLanguageCodes2/GetAvailableLanguageCodeCount2 instead of {original commands}.&lt;br /&gt;
&lt;br /&gt;
In official user-processes in the [[#Language]]-&amp;gt;[[#LanguageCode]] conversion function (MakeLanguageCode):&lt;br /&gt;
* During one-time init, GetAvailableLanguageCodes is used to initialize the LanguageCodes array cache, with max_entries=0xF (buffer size in u64s). [4.0.0+] GetAvailableLanguageCodes2 is now used with max_entries 0x40.&lt;br /&gt;
* [4.0.0+] When the input [[#Language]] is larger than the cached total_entries from the above command output, or [[#Language]] is negative, command MakeLanguageCode is used instead of the array.&lt;br /&gt;
&lt;br /&gt;
== GetLanguageCode ==&lt;br /&gt;
No input, returns an output [[#LanguageCode]]. This is the current system language.&lt;br /&gt;
&lt;br /&gt;
== GetAvailableLanguageCodes ==&lt;br /&gt;
Takes a type-0xA buffer containing the [[#LanguageCode]] output array, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== MakeLanguageCode ==&lt;br /&gt;
Takes an input [[#Language]], returns an output [[#LanguageCode]].&lt;br /&gt;
&lt;br /&gt;
== GetAvailableLanguageCodeCount ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== GetRegionCode ==&lt;br /&gt;
No input, returns a [[#RegionCode_2|RegionCode]].&lt;br /&gt;
&lt;br /&gt;
== GetAvailableLanguageCodes2 ==&lt;br /&gt;
Takes a type-0x6 buffer containing the [[#LanguageCode]] output array, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== GetAvailableLanguageCodeCount2 ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== GetKeyCodeMap ==&lt;br /&gt;
Takes a type-0x16 output buffer containing KeyCodeMap, official sw uses fixed size 0x1000. This is probably related to HID keyboard.&lt;br /&gt;
&lt;br /&gt;
== GetFirmwareVersionForDebug ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a 0x80-byte &amp;quot;nn::oe::FirmwareVersionForDebug&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This uses [[#GetDebugModeFlag]] internally, if the output flag is 0 an error is thrown.&lt;br /&gt;
&lt;br /&gt;
This runs the same code as GetFirmwareVersion2, with the last 0x80-bytes of the [[System_Version_Title|output]] being copied to the output buffer.&lt;br /&gt;
&lt;br /&gt;
= set:fd =&lt;br /&gt;
This is &amp;quot;nn::settings::IFirmwareDebugSettingsServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[4.0.0+] Only exposed if in [[SPL_services#IsDevelopment|development mode]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 2 || SetSettingsItemValue&lt;br /&gt;
|-&lt;br /&gt;
| 3 || ResetSettingsItemValue&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#ISettingsItemKeyIterator|CreateSettingsItemKeyIterator]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [4.0.0+] ReadSettings&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [4.0.0+] ResetSettings&lt;br /&gt;
|-&lt;br /&gt;
| 20 || [4.0.0+] SetWebInspectorFlag&lt;br /&gt;
|-&lt;br /&gt;
| 21 || [4.0.0+] SetAllowedSslHosts&lt;br /&gt;
|-&lt;br /&gt;
| 22 || [4.0.0+] SetHostFsMountPoint&lt;br /&gt;
|-&lt;br /&gt;
| 23 || [9.0.0+] SetMemoryUsageRateFlag&lt;br /&gt;
|-&lt;br /&gt;
| 24 || [20.0.0+] CommitSettings&lt;br /&gt;
|-&lt;br /&gt;
| 27 || [21.0.0+] SetHttpAuthConfigs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ISettingsItemKeyIterator ==&lt;br /&gt;
This is &amp;quot;nn::settings::ISettingsItemKeyIterator&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GoNext&lt;br /&gt;
|-&lt;br /&gt;
| 1 || GetKeySize&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GetKey&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= set:cal =&lt;br /&gt;
This is &amp;quot;nn::settings::IFactorySettingsServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [S1] [[#GetBluetoothBdAddress]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetConfigurationId1]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [S1] [[#GetAccelerometerOffset]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [S1] [[#GetAccelerometerScale]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [S1] [[#GetGyroscopeOffset]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [S1] [[#GetGyroscopeScale]]&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [[#GetWirelessLanMacAddress]]&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [S1] [[#GetWirelessLanCountryCodeCount]]&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [S1] [[#GetWirelessLanCountryCodes]]&lt;br /&gt;
|-&lt;br /&gt;
| 9 || [[#GetSerialNumber]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [S1] [[#SetInitialSystemAppletProgramId]]&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [S1] [[#SetOverlayDispProgramId]]&lt;br /&gt;
|-&lt;br /&gt;
| 12 || [[#GetBatteryLot]]&lt;br /&gt;
|-&lt;br /&gt;
| 14 || [S1] [[#GetEciDeviceCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 15 || [S1] [[#GetEticketDeviceCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 16 || [S1] [[#GetSslKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 17 || [S1] [[#GetSslCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 18 || [S1] [[#GetGameCardKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 19 || [S1] [[#GetGameCardCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 20 || [S1] [[#GetEciDeviceKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 21 || [S1] [[#GetEticketDeviceKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 22 || [S1] [[#GetSpeakerParameter]]&lt;br /&gt;
|-&lt;br /&gt;
| 23 || [S1] [4.0.0+] [[#GetLcdVendorId]]&lt;br /&gt;
|-&lt;br /&gt;
| 24 || [S1] [5.0.0+] [[#GetEciDeviceCertificate2]]&lt;br /&gt;
|-&lt;br /&gt;
| 25 || [S1] [5.0.0+] [[#GetEciDeviceKey2]]&lt;br /&gt;
|-&lt;br /&gt;
| 26 || [S1] [5.0.0+] [[#GetAmiiboKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 27 || [S1] [5.0.0+] [[#GetAmiiboEcqvCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 28 || [S1] [5.0.0+] [[#GetAmiiboEcdsaCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 29 || [S1] [5.0.0+] [[#GetAmiiboEcqvBlsKey]]&lt;br /&gt;
|-&lt;br /&gt;
| 30 || [S1] [5.0.0+] [[#GetAmiiboEcqvBlsCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 31 || [S1] [5.0.0+] [[#GetAmiiboEcqvBlsRootCertificate]]&lt;br /&gt;
|-&lt;br /&gt;
| 32 || [S1] [5.0.0+] [[#GetUsbTypeCPowerSourceCircuitVersion]]&lt;br /&gt;
|-&lt;br /&gt;
| 33 || [S1] [8.1.1+] [[#GetAnalogStickModuleTypeL]]&lt;br /&gt;
|-&lt;br /&gt;
| 34 || [S1] [8.1.1+] [[#GetAnalogStickModelParameterL]]&lt;br /&gt;
|-&lt;br /&gt;
| 35 || [S1] [8.1.1+] [[#GetAnalogStickFactoryCalibrationL]]&lt;br /&gt;
|-&lt;br /&gt;
| 36 || [S1] [8.1.1+] [[#GetAnalogStickModuleTypeR]]&lt;br /&gt;
|-&lt;br /&gt;
| 37 || [S1] [8.1.1+] [[#GetAnalogStickModelParameterR]]&lt;br /&gt;
|-&lt;br /&gt;
| 38 || [S1] [8.1.1+] [[#GetAnalogStickFactoryCalibrationR]]&lt;br /&gt;
|-&lt;br /&gt;
| 39 || [S1] [8.1.1+] [[#GetConsoleSixAxisSensorModuleType]]&lt;br /&gt;
|-&lt;br /&gt;
| 40 || [S1] [8.1.1+] [[#GetConsoleSixAxisSensorHorizontalOffset]]&lt;br /&gt;
|-&lt;br /&gt;
| 41 || [S1] [6.0.0+] [[#GetBatteryVersion]]&lt;br /&gt;
|-&lt;br /&gt;
| 42 || [S1] [10.0.0+] [[#GetDeviceId]]&lt;br /&gt;
|-&lt;br /&gt;
| 43 || [S1] [10.0.0+] [[#GetConsoleSixAxisSensorMountType]]&lt;br /&gt;
|-&lt;br /&gt;
| 44 || [S2] GetCpDeviceKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 45 || [S2] GetCpDeviceKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 46 || [S2] GetCpCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 47 || [S2] GetCpCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 48 || [S2] GetRaCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 49 || [S2] GetRaCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 50 || [S2] GetRaOemEkFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 51 || [S2] GetRaOemEkFile&lt;br /&gt;
|-&lt;br /&gt;
| 52 || [S2] GetRaPkaKekFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 53 || [S2] GetRaPkaKekFile&lt;br /&gt;
|-&lt;br /&gt;
| 54 || [S2] GetGcNxPkKekFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 55 || [S2] GetGcNxPkKekFile&lt;br /&gt;
|-&lt;br /&gt;
| 56 || [S2] GetGcUniqueImportKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 57 || [S2] GetGcUniqueImportKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 58 || [S2] GetGcUniqueEncryptionKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 59 || [S2] GetGcUniqueEncryptionKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 60 || [S2] GetGcCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 61 || [S2] GetGcCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 62 || [S2] GetGcUniqueKeyAFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 63 || [S2] GetGcUniqueKeyAFile&lt;br /&gt;
|-&lt;br /&gt;
| 64 || [S2] GetGcUniqueKeyBFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 65 || [S2] GetGcUniqueKeyBFile&lt;br /&gt;
|-&lt;br /&gt;
| 66 || [S2] GetGcNxKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 67 || [S2] GetGcNxKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 68 || [S2] GetGcNxCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 69 || [S2] GetGcNxCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 70 || [S2] GetWirelessLanRegulatoryDomain&lt;br /&gt;
|-&lt;br /&gt;
| 71 || [S2] GetDeviceId&lt;br /&gt;
|-&lt;br /&gt;
| 72 || [S2] GetBluetoothBdAddressSet&lt;br /&gt;
|-&lt;br /&gt;
| 73 || [S2] GetToolModel&lt;br /&gt;
|-&lt;br /&gt;
| 74 || [S2] IsRadioForbidden&lt;br /&gt;
|-&lt;br /&gt;
| 75 || [S2] GetDisplayModuleId&lt;br /&gt;
|-&lt;br /&gt;
| 76 || [S2] GetAnalogStickModuleTypeL&lt;br /&gt;
|-&lt;br /&gt;
| 77 || [S2] GetAnalogStickModelParameterL&lt;br /&gt;
|-&lt;br /&gt;
| 78 || [S2] GetAnalogStickFactoryCalibrationL&lt;br /&gt;
|-&lt;br /&gt;
| 79 || [S2] GetAnalogStickModuleTypeR&lt;br /&gt;
|-&lt;br /&gt;
| 80 || [S2] GetAnalogStickModelParameterR&lt;br /&gt;
|-&lt;br /&gt;
| 81 || [S2] GetAnalogStickFactoryCalibrationR&lt;br /&gt;
|-&lt;br /&gt;
| 82 || [S2] GetConsoleSixAxisSensorModuleType&lt;br /&gt;
|-&lt;br /&gt;
| 83 || [S2] GetConsoleSixAxisSensorMountType&lt;br /&gt;
|-&lt;br /&gt;
| 84 || [S2] GetConsoleSixAxisSensorFactoryCalibration&lt;br /&gt;
|-&lt;br /&gt;
| 85 || [S2] GetOta0DeviceKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 86 || [S2] GetOta0DeviceKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 87 || [S2] GetOta0CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 88 || [S2] GetOta0CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 89 || [S2] GetOta1DeviceKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 90 || [S2] GetOta1DeviceKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 91 || [S2] GetOta1CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 92 || [S2] GetOta1CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 93 || [S2] GetOta2DeviceKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 94 || [S2] GetOta2DeviceKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 95 || [S2] GetOta2CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 96 || [S2] GetOta2CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 97 || [S2] GetJc0CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 98 || [S2] GetJc0CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 99 || [S2] GetJc0PrivateKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [S2] GetJc0PrivateKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [S2] GetJc0PkKekFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [S2] GetJc0PkKekFile&lt;br /&gt;
|-&lt;br /&gt;
| 103 || [S2] GetJc1CertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 104 || [S2] GetJc1CertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 105 || [S2] GetJc1PrivateKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 106 || [S2] GetJc1PrivateKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 107 || [S2] GetJc1PkKekFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 108 || [S2] GetJc1PkKekFile&lt;br /&gt;
|-&lt;br /&gt;
| 109 || [S2] GetWirelessLanPowerTable&lt;br /&gt;
|-&lt;br /&gt;
| 110 || [S2] GetConsoleSixAxisSensorFactoryAccelerationLog&lt;br /&gt;
|-&lt;br /&gt;
| 111 || [S2] GetDrmCertificateFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 112 || [S2] GetDrmCertificateFile&lt;br /&gt;
|-&lt;br /&gt;
| 113 || [S2] GetCalibrationTimeStampUtc&lt;br /&gt;
|-&lt;br /&gt;
| 114 || [S2] GetEncryptedSecretDeviceIdFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 115 || [S2] GetEncryptedSecretDeviceIdFile&lt;br /&gt;
|-&lt;br /&gt;
| 116 || [S2] GetEncryptedSecretDeviceIdEncryptionKeyFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 117 || [S2] GetEncryptedSecretDeviceIdEncryptionKeyFile&lt;br /&gt;
|-&lt;br /&gt;
| 118 || [S2] &lt;br /&gt;
|-&lt;br /&gt;
| 119 || [22.0.0+] GetRegionCode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Used for accessing data [[Calibration|calibrated]] at the factory.&lt;br /&gt;
&lt;br /&gt;
== GetBluetoothBdAddress ==&lt;br /&gt;
No input. Returns a [[#BdAddress|BdAddress]].&lt;br /&gt;
&lt;br /&gt;
== GetConfigurationId1 ==&lt;br /&gt;
No input. Returns a [[#ConfigurationId1|ConfigurationId1]].&lt;br /&gt;
&lt;br /&gt;
== GetAccelerometerOffset ==&lt;br /&gt;
No input. Returns a [[#AccelerometerOffset|AccelerometerOffset]].&lt;br /&gt;
&lt;br /&gt;
== GetAccelerometerScale ==&lt;br /&gt;
No input. Returns a [[#AccelerometerScale|AccelerometerScale]].&lt;br /&gt;
&lt;br /&gt;
== GetGyroscopeOffset ==&lt;br /&gt;
No input. Returns a [[#GyroscopeOffset|GyroscopeOffset]].&lt;br /&gt;
&lt;br /&gt;
== GetGyroscopeScale ==&lt;br /&gt;
No input. Returns a [[#GyroscopeScale|GyroscopeScale]].&lt;br /&gt;
&lt;br /&gt;
== GetWirelessLanMacAddress ==&lt;br /&gt;
No input. Returns a [[#MacAddress|MacAddress]].&lt;br /&gt;
&lt;br /&gt;
== GetWirelessLanCountryCodeCount ==&lt;br /&gt;
No input. Returns a s32 &#039;&#039;&#039;OutCount&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== GetWirelessLanCountryCodes ==&lt;br /&gt;
Takes a type-0x16 output buffer containing an array of [[#CountryCode|CountryCode]]. Returns a s32 &#039;&#039;&#039;OutCount&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
== GetSerialNumber ==&lt;br /&gt;
No input. Returns a [[#SerialNumber|SerialNumber]].&lt;br /&gt;
&lt;br /&gt;
== SetInitialSystemAppletProgramId ==&lt;br /&gt;
Takes an input [[NCM_services#ProgramId|ProgramId]]. No output.&lt;br /&gt;
&lt;br /&gt;
== SetOverlayDispProgramId ==&lt;br /&gt;
Takes an input [[NCM_services#ProgramId|ProgramId]]. No output.&lt;br /&gt;
&lt;br /&gt;
== GetBatteryLot ==&lt;br /&gt;
No input. Returns a [[#BatteryLot|BatteryLot]].&lt;br /&gt;
&lt;br /&gt;
== GetEciDeviceCertificate ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#EccB233DeviceCertificate|EccB233DeviceCertificate]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the device certificate (ECC signed). This is identical to 3DS DeviceCert/CTCert besides the strings. NIM loads the DeviceId from this.&lt;br /&gt;
&lt;br /&gt;
== GetEticketDeviceCertificate ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#Rsa2048DeviceCertificate|Rsa2048DeviceCertificate]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the ETicket certificate (RSA signed).&lt;br /&gt;
&lt;br /&gt;
== GetSslKey ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#SslKey|SslKey]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the extended SSL key (0x130 bytes) from [[Calibration#CAL0|CAL0]]. If the extended key is not programmed then it falls back to the normal SSL key (0x110 bytes).&lt;br /&gt;
&lt;br /&gt;
Used by SSL-sysmodule, see [[SSL_services|here]].&lt;br /&gt;
&lt;br /&gt;
== GetSslCertificate ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#SslCertificate|SslCertificate]]. No output.&lt;br /&gt;
&lt;br /&gt;
Used by SSL-sysmodule, see [[SSL_services|here]].&lt;br /&gt;
&lt;br /&gt;
== GetGameCardKey ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#GameCardKey|GameCardKey]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the extended GameCard key (0x130 bytes) from [[Calibration#CAL0|CAL0]]. If the extended key is not programmed then it falls back to the normal GameCard key (0x110 bytes).&lt;br /&gt;
&lt;br /&gt;
== GetGameCardCertificate ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#GameCardCertificate|GameCardCertificate]]. No output.&lt;br /&gt;
&lt;br /&gt;
== GetEciDeviceKey ==&lt;br /&gt;
No input. Returns an [[#EccB233DeviceKey|EccB233DeviceKey]].&lt;br /&gt;
&lt;br /&gt;
Returns the extended device ECC-B233 key (0x50 bytes) from [[Calibration#CAL0|CAL0]]. If the extended key is not programmed then it falls back to the normal device ECC-B233 key (0x30 bytes).&lt;br /&gt;
&lt;br /&gt;
== GetEticketDeviceKey ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#Rsa2048DeviceKey|Rsa2048DeviceKey]]. No output.&lt;br /&gt;
&lt;br /&gt;
Returns the extended ETicket RSA-2048 key (0x240 bytes) from [[Calibration#CAL0|CAL0]]. If the extended key is not programmed then it falls back to the normal ETicket RSA-2048 key (0x220 bytes).&lt;br /&gt;
&lt;br /&gt;
== GetSpeakerParameter ==&lt;br /&gt;
No input. Returns a [[#SpeakerParameter|SpeakerParameter]].&lt;br /&gt;
&lt;br /&gt;
== GetLcdVendorId ==&lt;br /&gt;
No input. Returns a [[Calibration#LcdVendorId|LcdVendorId]].&lt;br /&gt;
&lt;br /&gt;
== GetEciDeviceCertificate2 ==&lt;br /&gt;
Same as [[#GetEciDeviceCertificate]], but returns a [[#Rsa2048DeviceCertificate|RSA-2048]] variant of the device certificate.&lt;br /&gt;
&lt;br /&gt;
== GetEciDeviceKey2 ==&lt;br /&gt;
Same as [[#GetEciDeviceKey]], but returns a [[#Rsa2048DeviceKey|RSA-2048]] variant of the device key.&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboKey ==&lt;br /&gt;
No input. Returns an [[#AmiiboKey|AmiiboKey]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcqvCertificate ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcqvCertificate|AmiiboEcqvCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcdsaCertificate ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcdsaCertificate|AmiiboEcdsaCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcqvBlsKey ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcqvBlsKey|AmiiboEcqvBlsKey]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcqvBlsCertificate ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcqvBlsCertificate|AmiiboEcqvBlsCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetAmiiboEcqvBlsRootCertificate ==&lt;br /&gt;
No input. Returns an [[#AmiiboEcqvBlsRootCertificate|AmiiboEcqvBlsRootCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetUsbTypeCPowerSourceCircuitVersion ==&lt;br /&gt;
No input. Returns an [[Calibration#UsbTypeCPowerSourceCircuit|UsbTypeCPowerSourceCircuitVersion]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickModuleTypeL ==&lt;br /&gt;
No input. Returns an [[Calibration#AnalogStickModuleType|AnalogStickModuleType]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickModelParameterL ==&lt;br /&gt;
No input. Returns an [[#AnalogStickModelParameter|AnalogStickModelParameter]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickFactoryCalibrationL ==&lt;br /&gt;
No input. Returns an [[#AnalogStickFactoryCalibration|AnalogStickFactoryCalibration]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickModuleTypeR ==&lt;br /&gt;
No input. Returns an [[Calibration#AnalogStickModuleType|AnalogStickModuleType]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickModelParameterR ==&lt;br /&gt;
No input. Returns an [[#AnalogStickModelParameter|AnalogStickModelParameter]].&lt;br /&gt;
&lt;br /&gt;
== GetAnalogStickFactoryCalibrationR ==&lt;br /&gt;
No input. Returns an [[#AnalogStickFactoryCalibration|AnalogStickFactoryCalibration]].&lt;br /&gt;
&lt;br /&gt;
== GetConsoleSixAxisSensorModuleType ==&lt;br /&gt;
No input. Returns a [[Calibration#ConsoleSixAxisSensorModuleType|ConsoleSixAxisSensorModuleType]].&lt;br /&gt;
&lt;br /&gt;
== GetConsoleSixAxisSensorHorizontalOffset ==&lt;br /&gt;
No input. Returns a [[#ConsoleSixAxisSensorHorizontalOffset|ConsoleSixAxisSensorHorizontalOffset]].&lt;br /&gt;
&lt;br /&gt;
== GetBatteryVersion ==&lt;br /&gt;
No input. Returns a [[Calibration#BatteryVersion|BatteryVersion]].&lt;br /&gt;
&lt;br /&gt;
== GetDeviceId ==&lt;br /&gt;
No input. Returns an u64 &#039;&#039;&#039;DeviceId&#039;&#039;&#039; by reading and converting the hexadecimal string at offset 0xC6 inside [[#EccB233DeviceCertificate]] or [[#Rsa2048DeviceCertificate]].&lt;br /&gt;
&lt;br /&gt;
== GetConsoleSixAxisSensorMountType ==&lt;br /&gt;
No input. Returns a [[Calibration#ConsoleSixAxisSensorMountType|ConsoleSixAxisSensorMountType]].&lt;br /&gt;
&lt;br /&gt;
= set:sys =&lt;br /&gt;
This is &amp;quot;nn::settings::ISystemSettingsServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#SetLanguageCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SetNetworkSettings&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GetNetworkSettings&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [S1] [[#GetFirmwareVersion]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [3.0.0+] GetFirmwareVersion2&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [S1] [5.0.0+] GetFirmwareVersionDigest&lt;br /&gt;
|-&lt;br /&gt;
| 7 || GetLockScreenFlag&lt;br /&gt;
|-&lt;br /&gt;
| 8 || SetLockScreenFlag&lt;br /&gt;
|-&lt;br /&gt;
| 9 || GetBacklightSettings&lt;br /&gt;
|-&lt;br /&gt;
| 10 || SetBacklightSettings&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [S1] SetBluetoothDevicesSettings&lt;br /&gt;
|-&lt;br /&gt;
| 12 || [S1] GetBluetoothDevicesSettings&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetExternalSteadyClockSourceId&lt;br /&gt;
|-&lt;br /&gt;
| 14 || SetExternalSteadyClockSourceId&lt;br /&gt;
|-&lt;br /&gt;
| 15 || GetUserSystemClockContext&lt;br /&gt;
|-&lt;br /&gt;
| 16 || SetUserSystemClockContext&lt;br /&gt;
|-&lt;br /&gt;
| 17 || [[#GetAccountSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 18 || [[#SetAccountSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 19 || GetAudioVolume&lt;br /&gt;
|-&lt;br /&gt;
| 20 || SetAudioVolume&lt;br /&gt;
|-&lt;br /&gt;
| 21 || [[#GetEulaVersions]]&lt;br /&gt;
|-&lt;br /&gt;
| 22 || [[#SetEulaVersions]]&lt;br /&gt;
|-&lt;br /&gt;
| 23 || [[#GetColorSetId]]&lt;br /&gt;
|-&lt;br /&gt;
| 24 || [[#SetColorSetId]]&lt;br /&gt;
|-&lt;br /&gt;
| 25 || [S1] GetConsoleInformationUploadFlag&lt;br /&gt;
|-&lt;br /&gt;
| 26 || [S1] SetConsoleInformationUploadFlag&lt;br /&gt;
|-&lt;br /&gt;
| 27 || [S1] GetAutomaticApplicationDownloadFlag&lt;br /&gt;
|-&lt;br /&gt;
| 28 || [S1] SetAutomaticApplicationDownloadFlag&lt;br /&gt;
|-&lt;br /&gt;
| 29 || [[#GetNotificationSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 30 || [[#SetNotificationSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 31 || [[#GetAccountNotificationSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 32 || [[#SetAccountNotificationSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 35 || GetVibrationMasterVolume&lt;br /&gt;
|-&lt;br /&gt;
| 36 || SetVibrationMasterVolume&lt;br /&gt;
|-&lt;br /&gt;
| 37 || GetSettingsItemValueSize&lt;br /&gt;
|-&lt;br /&gt;
| 38 || [[#GetSettingsItemValue]]&lt;br /&gt;
|-&lt;br /&gt;
| 39 || [[#GetTvSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 40 || [[#SetTvSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 41 || GetEdid&lt;br /&gt;
|-&lt;br /&gt;
| 42 || SetEdid&lt;br /&gt;
|-&lt;br /&gt;
| 43 || GetAudioOutputMode&lt;br /&gt;
|-&lt;br /&gt;
| 44 || SetAudioOutputMode&lt;br /&gt;
|-&lt;br /&gt;
| 45 || GetSpeakerAutoMuteFlag ([1.0.0-12.1.0] IsForceMuteOnHeadphoneRemoved)&lt;br /&gt;
|-&lt;br /&gt;
| 46 || SetSpeakerAutoMuteFlag ([1.0.0-12.1.0] SetForceMuteOnHeadphoneRemoved)&lt;br /&gt;
|-&lt;br /&gt;
| 47 || [[#GetQuestFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 48 || SetQuestFlag&lt;br /&gt;
|-&lt;br /&gt;
| 49 || [S1] [[#GetDataDeletionSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 50 || [S1] [[#SetDataDeletionSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 51 || [S1] GetInitialSystemAppletProgramId&lt;br /&gt;
|-&lt;br /&gt;
| 52 || [S1] GetOverlayDispProgramId&lt;br /&gt;
|-&lt;br /&gt;
| 53 || GetDeviceTimeZoneLocationName&lt;br /&gt;
|-&lt;br /&gt;
| 54 || SetDeviceTimeZoneLocationName&lt;br /&gt;
|-&lt;br /&gt;
| 55 || [S1] [[#GetWirelessCertificationFileSize]]&lt;br /&gt;
|-&lt;br /&gt;
| 56 || [S1] [[#GetWirelessCertificationFile]]&lt;br /&gt;
|-&lt;br /&gt;
| 57 || [[#SetRegionCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 58 || GetNetworkSystemClockContext&lt;br /&gt;
|-&lt;br /&gt;
| 59 || SetNetworkSystemClockContext&lt;br /&gt;
|-&lt;br /&gt;
| 60 || IsUserSystemClockAutomaticCorrectionEnabled&lt;br /&gt;
|-&lt;br /&gt;
| 61 || SetUserSystemClockAutomaticCorrectionEnabled&lt;br /&gt;
|-&lt;br /&gt;
| 62 || [[#GetDebugModeFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 63 || [[#GetPrimaryAlbumStorage]]&lt;br /&gt;
|-&lt;br /&gt;
| 64 || [[#SetPrimaryAlbumStorage]]&lt;br /&gt;
|-&lt;br /&gt;
| 65 || [S1] GetUsb30EnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 66 || [S1] SetUsb30EnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 67 || [[#GetBatteryLot]]&lt;br /&gt;
|-&lt;br /&gt;
| 68 || [[#GetSerialNumber]]&lt;br /&gt;
|-&lt;br /&gt;
| 69 || GetNfcEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 70 || SetNfcEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 71 || [[#GetSleepSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 72 || [[#SetSleepSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 73 || GetWirelessLanEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 74 || SetWirelessLanEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 75 || [S1] [[#GetInitialLaunchSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 76 || [S1] [[#SetInitialLaunchSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 77 || [[#GetDeviceNickName]]&lt;br /&gt;
|-&lt;br /&gt;
| 78 || [[#SetDeviceNickName]]&lt;br /&gt;
|-&lt;br /&gt;
| 79 || [[#GetProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 80 || [S1] GetLdnChannel&lt;br /&gt;
|-&lt;br /&gt;
| 81 || [S1] SetLdnChannel&lt;br /&gt;
|-&lt;br /&gt;
| 82 || AcquireTelemetryDirtyFlagEventHandle&lt;br /&gt;
|-&lt;br /&gt;
| 83 || GetTelemetryDirtyFlags&lt;br /&gt;
|-&lt;br /&gt;
| 84 || GetPtmBatteryLot&lt;br /&gt;
|-&lt;br /&gt;
| 85 || SetPtmBatteryLot&lt;br /&gt;
|-&lt;br /&gt;
| 86 || GetPtmFuelGaugeParameter&lt;br /&gt;
|-&lt;br /&gt;
| 87 || SetPtmFuelGaugeParameter&lt;br /&gt;
|-&lt;br /&gt;
| 88 || GetBluetoothEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 89 || SetBluetoothEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 90 || [[#GetMiiAuthorId]]&lt;br /&gt;
|-&lt;br /&gt;
| 91 || SetShutdownRtcValue&lt;br /&gt;
|-&lt;br /&gt;
| 92 || GetShutdownRtcValue&lt;br /&gt;
|-&lt;br /&gt;
| 93 || AcquireFatalDirtyFlagEventHandle&lt;br /&gt;
|-&lt;br /&gt;
| 94 || GetFatalDirtyFlags&lt;br /&gt;
|-&lt;br /&gt;
| 95 || [2.0.0+] GetAutoUpdateEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 96 || [2.0.0+] SetAutoUpdateEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 97 || [S1] [2.0.0+] GetNxControllerSettings&lt;br /&gt;
|-&lt;br /&gt;
| 98 || [S1] [2.0.0+] SetNxControllerSettings&lt;br /&gt;
|-&lt;br /&gt;
| 99 || [2.0.0+] GetBatteryPercentageFlag&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [2.0.0+] SetBatteryPercentageFlag&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [S1] [2.0.0+] GetExternalRtcResetFlag&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [S1] [2.0.0+] SetExternalRtcResetFlag&lt;br /&gt;
|-&lt;br /&gt;
| 103 || [3.0.0+] GetUsbFullKeyEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 104 || [3.0.0+] SetUsbFullKeyEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 105 || [3.0.0+] SetExternalSteadyClockInternalOffset&lt;br /&gt;
|-&lt;br /&gt;
| 106 || [3.0.0+] GetExternalSteadyClockInternalOffset&lt;br /&gt;
|-&lt;br /&gt;
| 107 || [3.0.0+] GetBacklightSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 108 || [3.0.0+] SetBacklightSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 109 || [3.0.0+] GetHeadphoneVolumeWarningCount&lt;br /&gt;
|-&lt;br /&gt;
| 110 || [3.0.0+] SetHeadphoneVolumeWarningCount&lt;br /&gt;
|-&lt;br /&gt;
| 111 || [S1] [3.0.0+] GetBluetoothAfhEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 112 || [S1] [3.0.0+] SetBluetoothAfhEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 113 || [S1] [3.0.0+] GetBluetoothBoostEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 114 || [S1] [3.0.0+] SetBluetoothBoostEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 115 || [3.0.0+] GetInRepairProcessEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 116 || [3.0.0+] SetInRepairProcessEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 117 || [S1] [3.0.0+] GetHeadphoneVolumeUpdateFlag&lt;br /&gt;
|-&lt;br /&gt;
| 118 || [S1] [3.0.0+] SetHeadphoneVolumeUpdateFlag&lt;br /&gt;
|-&lt;br /&gt;
| 119 || [3.0.0-14.1.2] NeedsToUpdateHeadphoneVolume&lt;br /&gt;
|-&lt;br /&gt;
| 120 || [3.0.0+] GetPushNotificationActivityModeOnSleep&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [3.0.0+] SetPushNotificationActivityModeOnSleep&lt;br /&gt;
|-&lt;br /&gt;
| 122 || [4.0.0+] [[#GetServiceDiscoveryControlSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 123 || [4.0.0+] SetServiceDiscoveryControlSettings&lt;br /&gt;
|-&lt;br /&gt;
| 124 || [4.0.0+] [[#GetErrorReportSharePermission]]&lt;br /&gt;
|-&lt;br /&gt;
| 125 || [4.0.0+] [[#SetErrorReportSharePermission]]&lt;br /&gt;
|-&lt;br /&gt;
| 126 || [4.0.0+] [[#GetAppletLaunchFlags]]&lt;br /&gt;
|-&lt;br /&gt;
| 127 || [4.0.0+] [[#SetAppletLaunchFlags]]&lt;br /&gt;
|-&lt;br /&gt;
| 128 || [S1] [4.0.0+] GetConsoleSixAxisSensorAccelerationBias&lt;br /&gt;
|-&lt;br /&gt;
| 129 || [S1] [4.0.0+] SetConsoleSixAxisSensorAccelerationBias&lt;br /&gt;
|-&lt;br /&gt;
| 130 || [S1] [4.0.0+] GetConsoleSixAxisSensorAngularVelocityBias&lt;br /&gt;
|-&lt;br /&gt;
| 131 || [S1] [4.0.0+] SetConsoleSixAxisSensorAngularVelocityBias&lt;br /&gt;
|-&lt;br /&gt;
| 132 || [S1] [4.0.0+] GetConsoleSixAxisSensorAccelerationGain&lt;br /&gt;
|-&lt;br /&gt;
| 133 || [S1] [4.0.0+] SetConsoleSixAxisSensorAccelerationGain&lt;br /&gt;
|-&lt;br /&gt;
| 134 || [S1] [4.0.0+] GetConsoleSixAxisSensorAngularVelocityGain&lt;br /&gt;
|-&lt;br /&gt;
| 135 || [S1] [4.0.0+] SetConsoleSixAxisSensorAngularVelocityGain&lt;br /&gt;
|-&lt;br /&gt;
| 136 || [4.0.0+] [[#GetKeyboardLayout]]&lt;br /&gt;
|-&lt;br /&gt;
| 137 || [4.0.0+] [[#SetKeyboardLayout]]&lt;br /&gt;
|-&lt;br /&gt;
| 138 || [4.0.0+] GetWebInspectorFlag&lt;br /&gt;
|-&lt;br /&gt;
| 139 || [4.0.0+] [[#GetAllowedSslHosts]]&lt;br /&gt;
|-&lt;br /&gt;
| 140 || [4.0.0+] GetHostFsMountPoint&lt;br /&gt;
|-&lt;br /&gt;
| 141 || [5.0.0+] GetRequiresRunRepairTimeReviser&lt;br /&gt;
|-&lt;br /&gt;
| 142 || [5.0.0+] SetRequiresRunRepairTimeReviser&lt;br /&gt;
|-&lt;br /&gt;
| 143 || [S1] [5.0.0+] SetBlePairingSettings&lt;br /&gt;
|-&lt;br /&gt;
| 144 || [S1] [5.0.0+] GetBlePairingSettings&lt;br /&gt;
|-&lt;br /&gt;
| 145 || [S1] [5.0.0+] GetConsoleSixAxisSensorAngularVelocityTimeBias&lt;br /&gt;
|-&lt;br /&gt;
| 146 || [S1] [5.0.0+] SetConsoleSixAxisSensorAngularVelocityTimeBias&lt;br /&gt;
|-&lt;br /&gt;
| 147 || [S1] [5.0.0+] GetConsoleSixAxisSensorAngularAcceleration&lt;br /&gt;
|-&lt;br /&gt;
| 148 || [S1] [5.0.0+] SetConsoleSixAxisSensorAngularAcceleration&lt;br /&gt;
|-&lt;br /&gt;
| 149 || [5.0.0+] [[#GetRebootlessSystemUpdateVersion]]&lt;br /&gt;
|-&lt;br /&gt;
| 150 || [5.0.0+] GetDeviceTimeZoneLocationUpdatedTime&lt;br /&gt;
|-&lt;br /&gt;
| 151 || [5.0.0+] SetDeviceTimeZoneLocationUpdatedTime&lt;br /&gt;
|-&lt;br /&gt;
| 152 || [6.0.0+] GetUserSystemClockAutomaticCorrectionUpdatedTime&lt;br /&gt;
|-&lt;br /&gt;
| 153 || [6.0.0+] SetUserSystemClockAutomaticCorrectionUpdatedTime&lt;br /&gt;
|-&lt;br /&gt;
| 154 || [S1] [6.0.0+] GetAccountOnlineStorageSettings&lt;br /&gt;
|-&lt;br /&gt;
| 155 || [S1] [6.0.0+] SetAccountOnlineStorageSettings&lt;br /&gt;
|-&lt;br /&gt;
| 156 || [S1] [6.0.0+] GetPctlReadyFlag&lt;br /&gt;
|-&lt;br /&gt;
| 157 || [S1] [6.0.0+] SetPctlReadyFlag&lt;br /&gt;
|-&lt;br /&gt;
| 158 || [S1] [8.1.1+] GetAnalogStickUserCalibrationL&lt;br /&gt;
|-&lt;br /&gt;
| 159 || [S1] [8.1.1+] SetAnalogStickUserCalibrationL&lt;br /&gt;
|-&lt;br /&gt;
| 160 || [S1] [8.1.1+] GetAnalogStickUserCalibrationR&lt;br /&gt;
|-&lt;br /&gt;
| 161 || [S1] [8.1.1+] SetAnalogStickUserCalibrationR&lt;br /&gt;
|-&lt;br /&gt;
| 162 || [6.0.0+] GetPtmBatteryVersion&lt;br /&gt;
|-&lt;br /&gt;
| 163 || [6.0.0+] SetPtmBatteryVersion&lt;br /&gt;
|-&lt;br /&gt;
| 164 || [6.0.0+] GetUsb30HostEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 165 || [6.0.0+] SetUsb30HostEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 166 || [6.0.0+] GetUsb30DeviceEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 167 || [6.0.0+] SetUsb30DeviceEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 168 || [S1] [7.0.0+] GetThemeId&lt;br /&gt;
|-&lt;br /&gt;
| 169 || [S1] [7.0.0+] SetThemeId&lt;br /&gt;
|-&lt;br /&gt;
| 170 || [7.0.0+] [[#GetChineseTraditionalInputMethod]]&lt;br /&gt;
|-&lt;br /&gt;
| 171 || [7.0.0+] [[#SetChineseTraditionalInputMethod]]&lt;br /&gt;
|-&lt;br /&gt;
| 172 || [7.0.0+] GetPtmCycleCountReliability&lt;br /&gt;
|-&lt;br /&gt;
| 173 || [7.0.0+] SetPtmCycleCountReliability&lt;br /&gt;
|-&lt;br /&gt;
| 174 || [8.1.1+] [[#GetHomeMenuScheme]]&lt;br /&gt;
|-&lt;br /&gt;
| 175 || [S1] [7.0.0+] GetThemeSettings&lt;br /&gt;
|-&lt;br /&gt;
| 176 || [S1] [7.0.0+] SetThemeSettings&lt;br /&gt;
|-&lt;br /&gt;
| 177 || [S1] [7.0.0+] GetThemeKey&lt;br /&gt;
|-&lt;br /&gt;
| 178 || [S1] [7.0.0+] SetThemeKey&lt;br /&gt;
|-&lt;br /&gt;
| 179 || [8.0.0+] GetZoomFlag&lt;br /&gt;
|-&lt;br /&gt;
| 180 || [8.0.0+] SetZoomFlag&lt;br /&gt;
|-&lt;br /&gt;
| 181 || [S1] [8.0.0+] [[#GetT]]&lt;br /&gt;
|-&lt;br /&gt;
| 182 || [S1] [8.0.0+] [[#SetT]]&lt;br /&gt;
|-&lt;br /&gt;
| 183 || [9.0.0+] [[#GetPlatformRegion]]&lt;br /&gt;
|-&lt;br /&gt;
| 184 || [9.0.0+] [[#SetPlatformRegion]]&lt;br /&gt;
|-&lt;br /&gt;
| 185 || [9.0.0+] [[#GetHomeMenuSchemeModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 186 || [9.0.0+] [[#GetMemoryUsageRateFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 187 || [S1] [9.0.0+] [[#GetTouchScreenMode]]&lt;br /&gt;
|-&lt;br /&gt;
| 188 || [S1] [9.0.0+] [[#SetTouchScreenMode]]&lt;br /&gt;
|-&lt;br /&gt;
| 189 || [S1] [10.0.0+] [[#GetButtonConfigSettingsFull]]&lt;br /&gt;
|-&lt;br /&gt;
| 190 || [S1] [10.0.0+] [[#SetButtonConfigSettingsFull]]&lt;br /&gt;
|-&lt;br /&gt;
| 191 || [S1] [10.0.0+] [[#GetButtonConfigSettingsEmbedded]]&lt;br /&gt;
|-&lt;br /&gt;
| 192 || [S1] [10.0.0+] [[#SetButtonConfigSettingsEmbedded]]&lt;br /&gt;
|-&lt;br /&gt;
| 193 || [S1] [10.0.0+] [[#GetButtonConfigSettingsLeft]]&lt;br /&gt;
|-&lt;br /&gt;
| 194 || [S1] [10.0.0+] [[#SetButtonConfigSettingsLeft]]&lt;br /&gt;
|-&lt;br /&gt;
| 195 || [S1] [10.0.0+] [[#GetButtonConfigSettingsRight]]&lt;br /&gt;
|-&lt;br /&gt;
| 196 || [S1] [10.0.0+] [[#SetButtonConfigSettingsRight]]&lt;br /&gt;
|-&lt;br /&gt;
| 197 || [S1] [10.0.0+] [[#GetButtonConfigRegisteredSettingsEmbedded]]&lt;br /&gt;
|-&lt;br /&gt;
| 198 || [S1] [10.0.0+] [[#SetButtonConfigRegisteredSettingsEmbedded]]&lt;br /&gt;
|-&lt;br /&gt;
| 199 || [S1] [10.0.0+] [[#GetButtonConfigRegisteredSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [S1] [10.0.0+] [[#SetButtonConfigRegisteredSettings]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [10.1.0+] [[#GetFieldTestingFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [10.1.0+] [[#SetFieldTestingFlag]]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [11.0.0+] GetPanelCrcMode&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [11.0.0+] SetPanelCrcMode&lt;br /&gt;
|-&lt;br /&gt;
| 205 || [S1] [13.0.0+] GetNxControllerSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 206 || [S1] [13.0.0+] SetNxControllerSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 207 || [S1] [14.0.0+] GetHearingProtectionSafeguardFlag&lt;br /&gt;
|-&lt;br /&gt;
| 208 || [S1] [14.0.0+] SetHearingProtectionSafeguardFlag&lt;br /&gt;
|-&lt;br /&gt;
| 209 || [S1] [14.0.0+] GetHearingProtectionSafeguardRemainingTime&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [S1] [14.0.0+] SetHearingProtectionSafeguardRemainingTime&lt;br /&gt;
|-&lt;br /&gt;
| 211 || [S2] GetWirelessCertificationHtmlFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 212 || [S2] GetWirelessCertificationHtmlFile&lt;br /&gt;
|-&lt;br /&gt;
| 213 || [S2] GetWirelessCertificationJpegFileSize&lt;br /&gt;
|-&lt;br /&gt;
| 214 || [S2] GetWirelessCertificationJpegFile&lt;br /&gt;
|-&lt;br /&gt;
| 215 || [S2] GetHighContrastFlag&lt;br /&gt;
|-&lt;br /&gt;
| 216 || [S2] SetHighContrastFlag&lt;br /&gt;
|-&lt;br /&gt;
| 217 || [S2] GetTextToSpeechFlag&lt;br /&gt;
|-&lt;br /&gt;
| 218 || [S2] SetTextToSpeechFlag&lt;br /&gt;
|-&lt;br /&gt;
| 219 || [S2] [[#GetTextMagnificationRatio]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [S2] SetTextMagnificationRatio&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [17.0.0+] GetForceMonauralOutputFlag&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [17.0.0+] SetForceMonauralOutputFlag&lt;br /&gt;
|-&lt;br /&gt;
| 223 || [S2] GetUsbAudioVolumeSettings&lt;br /&gt;
|-&lt;br /&gt;
| 224 || [S2] SetUsbAudioVolumeSettings&lt;br /&gt;
|-&lt;br /&gt;
| 225 || [S2] GetTitleIconKeepFlag&lt;br /&gt;
|-&lt;br /&gt;
| 226 || [S2] SetTitleIconKeepFlag&lt;br /&gt;
|-&lt;br /&gt;
| 227 || [S2] GetBoldTextFlag&lt;br /&gt;
|-&lt;br /&gt;
| 228 || [S2] SetBoldTextFlag&lt;br /&gt;
|-&lt;br /&gt;
| 229 || [S2] GetSpeechToTextFlag&lt;br /&gt;
|-&lt;br /&gt;
| 230 || [S2] SetSpeechToTextFlag&lt;br /&gt;
|-&lt;br /&gt;
| 235 || [S2] GetColorFilterType&lt;br /&gt;
|-&lt;br /&gt;
| 236 || [S2] SetColorFilterType&lt;br /&gt;
|-&lt;br /&gt;
| 237 || [S2] GetPrioritizedOutputAudioDeviceSettings&lt;br /&gt;
|-&lt;br /&gt;
| 238 || [S2] SetPrioritizedOutputAudioDeviceSettings&lt;br /&gt;
|-&lt;br /&gt;
| 239 || [S2] GetPrioritizedInputAudioDeviceSettings&lt;br /&gt;
|-&lt;br /&gt;
| 240 || [S2] SetPrioritizedInputAudioDeviceSettings&lt;br /&gt;
|-&lt;br /&gt;
| 241 || [S2] GetTextToSpeechVoiceTypeForUi&lt;br /&gt;
|-&lt;br /&gt;
| 242 || [S2] SetTextToSpeechVoiceTypeForUi&lt;br /&gt;
|-&lt;br /&gt;
| 243 || [S2] GetLcdFlags&lt;br /&gt;
|-&lt;br /&gt;
| 244 || [S2] SetLcdFlags&lt;br /&gt;
|-&lt;br /&gt;
| 245 || [S2] GetTvHdrSettings&lt;br /&gt;
|-&lt;br /&gt;
| 246 || [S2] SetTvHdrSettings&lt;br /&gt;
|-&lt;br /&gt;
| 247 || [S2] IsColorInversionEnabled&lt;br /&gt;
|-&lt;br /&gt;
| 248 || [S2] SetColorInversionEnabled&lt;br /&gt;
|-&lt;br /&gt;
| 249 || [S2] GetKeyRemapEnableFlagOnQuickSettings&lt;br /&gt;
|-&lt;br /&gt;
| 250 || [S2] SetKeyRemapEnableFlagOnQuickSettings&lt;br /&gt;
|-&lt;br /&gt;
| 251 || [18.0.0+] GetAccountIdentificationSettings&lt;br /&gt;
|-&lt;br /&gt;
| 252 || [18.0.0+] SetAccountIdentificationSettings&lt;br /&gt;
|-&lt;br /&gt;
| 253 || [S2] GetDeviceLockPinCodeLength&lt;br /&gt;
|-&lt;br /&gt;
| 254 || [S2] GetDeviceLockPinCode&lt;br /&gt;
|-&lt;br /&gt;
| 255 || [S2] SetDeviceLockPinCode&lt;br /&gt;
|-&lt;br /&gt;
| 256 || [S2] GetDeviceLockEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 257 || [S2] GetDeviceLockStartPenaltyTime&lt;br /&gt;
|-&lt;br /&gt;
| 258 || [S2] SetDeviceLockStartPenaltyTime&lt;br /&gt;
|-&lt;br /&gt;
| 259 || [S2] GetDeviceLockErrorCount&lt;br /&gt;
|-&lt;br /&gt;
| 260 || [S2] SetDeviceLockErrorCount&lt;br /&gt;
|-&lt;br /&gt;
| 261 || [S2] GetBatteryCareModeEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 262 || [S2] SetBatteryCareModeEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 263 || [20.0.0+] AcquireVphymDirtyFlagEventHandle&lt;br /&gt;
|-&lt;br /&gt;
| 264 || [20.0.0+] GetVphymDirtyFlags&lt;br /&gt;
|-&lt;br /&gt;
| 265 || [S2] GetInitialLaunchSettings&lt;br /&gt;
|-&lt;br /&gt;
| 266 || [S2] SetInitialLaunchSettings&lt;br /&gt;
|-&lt;br /&gt;
| 267 || [S2] GetManufacturingTimeStamp&lt;br /&gt;
|-&lt;br /&gt;
| 268 || [S2] SetManufacturingTimeStamp&lt;br /&gt;
|-&lt;br /&gt;
| 269 || [S2] GetInputNoiseReductionForCommunicationFlag&lt;br /&gt;
|-&lt;br /&gt;
| 270 || [S2] SetInputNoiseReductionForCommunicationFlag&lt;br /&gt;
|-&lt;br /&gt;
| 271 || [S2] GetChatTranscriptionSettings&lt;br /&gt;
|-&lt;br /&gt;
| 272 || [S2] SetChatTranscriptionSettings&lt;br /&gt;
|-&lt;br /&gt;
| 273 || [S2] GetBuiltInMicrophoneGain&lt;br /&gt;
|-&lt;br /&gt;
| 274 || [S2] SetBuiltInMicrophoneGain&lt;br /&gt;
|-&lt;br /&gt;
| 275 || [S2] GetBuiltInMicrophoneJackGain&lt;br /&gt;
|-&lt;br /&gt;
| 276 || [S2] SetBuiltInMicrophoneJackGain&lt;br /&gt;
|-&lt;br /&gt;
| 277 || [S2] GetUsbAudioInputDeviceGainSettings&lt;br /&gt;
|-&lt;br /&gt;
| 278 || [S2] SetUsbAudioInputDeviceGainSettings&lt;br /&gt;
|-&lt;br /&gt;
| 279 || [S2] SetBluetoothStackFlag&lt;br /&gt;
|-&lt;br /&gt;
| 280 || [S2] SetHidDebugOcdUsbFlag&lt;br /&gt;
|-&lt;br /&gt;
| 281 || [S2] SetHidDebugRailFlag&lt;br /&gt;
|-&lt;br /&gt;
| 282 || [20.0.0+] [[#ConvertToProductModel|ConvertToProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 283 || [20.0.0+] [[#ConvertToProductModelName|ConvertToProductModelName]]&lt;br /&gt;
|-&lt;br /&gt;
| 284 || [S2] GetSaveDataPurgedForRepairFlag&lt;br /&gt;
|-&lt;br /&gt;
| 285 || [S2] SetSaveDataPurgedForRepairFlag&lt;br /&gt;
|-&lt;br /&gt;
| 286 || [S2] [20.0.0+] GetAppletParameterSet&lt;br /&gt;
|-&lt;br /&gt;
| 287 || [S2] [20.0.0+] SetAppletParameterSet&lt;br /&gt;
|-&lt;br /&gt;
| 288 || [S2] [20.0.0+] BindChatTranscriptionSettingsChangedEvent&lt;br /&gt;
|-&lt;br /&gt;
| 289 || [20.0.0+] GetDefaultAccountIdentificationFlagSet&lt;br /&gt;
|-&lt;br /&gt;
| 290 || [S2] [20.0.0+] GetMouseEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 291 || [S2] [20.0.0+] SetMouseEnableFlag&lt;br /&gt;
|-&lt;br /&gt;
| 292 || [S2] [20.0.0+] GetTextToSpeechVoiceVolume&lt;br /&gt;
|-&lt;br /&gt;
| 293 || [S2] [20.0.0+] SetTextToSpeechVoiceVolume&lt;br /&gt;
|-&lt;br /&gt;
| 294 || [S2] [20.0.0+] GetTextToSpeechVoiceSpeed&lt;br /&gt;
|-&lt;br /&gt;
| 295 || [S2] [20.0.0+] SetTextToSpeechVoiceSpeed&lt;br /&gt;
|-&lt;br /&gt;
| 296 || [S2] [20.0.0+] GetSleepSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 297 || [S2] [20.0.0+] SetSleepSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 298 || [S2] [20.0.0+] GetMousePointerSpeedScale&lt;br /&gt;
|-&lt;br /&gt;
| 299 || [S2] [20.0.0+] SetMousePointerSpeedScale&lt;br /&gt;
|-&lt;br /&gt;
| 300 || [20.0.0+] AcquirePushNotificationDirtyFlagEventHandle&lt;br /&gt;
|-&lt;br /&gt;
| 301 || [20.0.0+] GetPushNotificationDirtyFlags&lt;br /&gt;
|-&lt;br /&gt;
| 302 || [S2] [20.0.0+] GetTvHdrSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 303 || [S2] [20.0.0+] SetTvHdrSettingsEx&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [S2] [20.0.0+] GetOunceProControllerMicrophoneJackGain&lt;br /&gt;
|-&lt;br /&gt;
| 305 || [S2] [20.0.0+] SetOunceProControllerMicrophoneJackGain&lt;br /&gt;
|-&lt;br /&gt;
| 306 || [20.0.0+] GetPinCodeReregistrationGuideAccounts&lt;br /&gt;
|-&lt;br /&gt;
| 307 || [20.0.0+] SetPinCodeReregistrationGuideAccounts&lt;br /&gt;
|-&lt;br /&gt;
| 308 || [S2] [20.0.0+] GetChatTranscriptionSettings&lt;br /&gt;
|-&lt;br /&gt;
| 309 || [S2] [20.0.0+] SetChatTranscriptionSettings&lt;br /&gt;
|-&lt;br /&gt;
| 310 || [S2] [20.0.0+] GetDeviceLockPinCodeLsbParity&lt;br /&gt;
|-&lt;br /&gt;
| 311 || [S2] [20.0.0+] VerifyDeviceLockPinCode&lt;br /&gt;
|-&lt;br /&gt;
| 312 || [S2] [20.0.0+] GetDeviceLockVeificationForbiddenFlag&lt;br /&gt;
|-&lt;br /&gt;
| 315 || [21.0.0+] GetHttpAuthConfigs&lt;br /&gt;
|-&lt;br /&gt;
| 319 || [21.0.0+] GetAccountUserSettings&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [21.0.0+] SetAccountUserSettings&lt;br /&gt;
|-&lt;br /&gt;
| 321 || [21.0.0+] GetDefaultAccountUserSettings&lt;br /&gt;
|-&lt;br /&gt;
| 324 || [22.0.0+] GetPtmQhClearCount&lt;br /&gt;
|-&lt;br /&gt;
| 325 || [22.0.0+] SetPtmQhClearCount&lt;br /&gt;
|-&lt;br /&gt;
| 326 || [22.0.0+] GetAirPlaneModeRestoreFlagSet&lt;br /&gt;
|-&lt;br /&gt;
| 327 || [22.0.0+] SetAirPlaneModeRestoreFlagSet&lt;br /&gt;
|-&lt;br /&gt;
| 328 || [22.0.0+] DeleteSettingsPerAccount&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Official user-processes gets a new service session handle each time a set:sys cmd is used, with the session being closed afterwards.&lt;br /&gt;
&lt;br /&gt;
== SetLanguageCode ==&lt;br /&gt;
Takes an input [[#LanguageCode]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetFirmwareVersion ==&lt;br /&gt;
Takes a type-0x1A output buffer. User-processes use hard-coded size 0x100.&lt;br /&gt;
&lt;br /&gt;
This was removed with S2.&lt;br /&gt;
&lt;br /&gt;
If needed, reads the content of the [[System_Version_Title]] &amp;quot;/file&amp;quot; into state. This is only done once.&lt;br /&gt;
&lt;br /&gt;
Then the above 0x100-byte data is copied to the output buffer.&lt;br /&gt;
&lt;br /&gt;
== GetAccountSettings ==&lt;br /&gt;
No input, returns an output [[#AccountSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetAccountSettings ==&lt;br /&gt;
Takes an input [[#AccountSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetEulaVersions ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#EulaVersion]], returns an output s32 total_out.&lt;br /&gt;
&lt;br /&gt;
== SetEulaVersions ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#EulaVersion]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetColorSetId ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
This is the current Theme set by System Settings.&lt;br /&gt;
&lt;br /&gt;
* 0: &amp;quot;Basic White&amp;quot;&lt;br /&gt;
* 1: &amp;quot;Basic Black&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== SetColorSetId ==&lt;br /&gt;
Takes an input s32, no output.&lt;br /&gt;
&lt;br /&gt;
== GetNotificationSettings ==&lt;br /&gt;
No input, returns an output [[#NotificationSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetNotificationSettings ==&lt;br /&gt;
Takes an input [[#NotificationSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetAccountNotificationSettings ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#AccountNotificationSettings]], returns an output s32 total_out.&lt;br /&gt;
&lt;br /&gt;
== SetAccountNotificationSettings ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#AccountNotificationSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetSettingsItemValue ==&lt;br /&gt;
Takes two type-0x19 input buffers and a type-0x6 output buffer. Returns an output u64 for the actual size written to the outbuf.&lt;br /&gt;
&lt;br /&gt;
The outbuf_size is compared with the config_size. When config_size is larger than outbuf_size, outbuf_size is used for the memcpy, otherwise config_size is used. Afterwards the size used for the memcpy is written to output(see above).&lt;br /&gt;
&lt;br /&gt;
If loading from main config fails, it will also attempt to load config from various state if the input strings match hard-coded strings.&lt;br /&gt;
&lt;br /&gt;
== GetTvSettings ==&lt;br /&gt;
No input, returns an output [[#TvSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetTvSettings ==&lt;br /&gt;
Takes an input [[#TvSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetDebugModeFlag ==&lt;br /&gt;
Returns an output u8.&lt;br /&gt;
&lt;br /&gt;
Loads the 1-byte config for &amp;lt;&amp;quot;settings_debug&amp;quot;, &amp;quot;is_debug_mode_enabled&amp;quot;&amp;gt;. If that fails, value 0x1 is written to output. This uses the same func as ReadSetting internally.&lt;br /&gt;
&lt;br /&gt;
Returned retval is always 0.&lt;br /&gt;
&lt;br /&gt;
== GetPrimaryAlbumStorage ==&lt;br /&gt;
No input, returns an output s32 [[#PrimaryAlbumStorage]].&lt;br /&gt;
&lt;br /&gt;
== SetPrimaryAlbumStorage ==&lt;br /&gt;
Takes an input s32 [[#PrimaryAlbumStorage]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetBatteryLot ==&lt;br /&gt;
No input, returns an output [[#BatteryLot]].&lt;br /&gt;
&lt;br /&gt;
== GetSerialNumber ==&lt;br /&gt;
Returns the 0x18-byte SerialNumber string.&lt;br /&gt;
&lt;br /&gt;
== GetSleepSettings ==&lt;br /&gt;
No input, returns an output [[#SleepSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetSleepSettings ==&lt;br /&gt;
Takes an input [[#SleepSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetInitialLaunchSettings ==&lt;br /&gt;
No input, returns an output [[#InitialLaunchSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetInitialLaunchSettings ==&lt;br /&gt;
Takes an input [[#InitialLaunchSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetDeviceNickName ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#DeviceNickName]].&lt;br /&gt;
&lt;br /&gt;
With [10.1.0+] sdknso now uses the set cmd instead of the setsys cmd.&lt;br /&gt;
&lt;br /&gt;
== SetDeviceNickName ==&lt;br /&gt;
Takes a type-0x15 input buffer containing a [[#DeviceNickName]].&lt;br /&gt;
&lt;br /&gt;
== GetProductModel ==&lt;br /&gt;
No input, returns an output s32 [[#ProductModel|ProductModel]].&lt;br /&gt;
&lt;br /&gt;
== GetMiiAuthorId ==&lt;br /&gt;
No input, returns an output &amp;quot;nn::util::Uuid&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== GetServiceDiscoveryControlSettings ==&lt;br /&gt;
Returns an u32 [[#ServiceDiscoveryControlSettings|ServiceDiscoveryControlSettings]].&lt;br /&gt;
&lt;br /&gt;
== GetErrorReportSharePermission ==&lt;br /&gt;
No input, returns an output s32 [[#ErrorReportSharePermission]].&lt;br /&gt;
&lt;br /&gt;
== SetErrorReportSharePermission ==&lt;br /&gt;
Takes an input s32 [[#ErrorReportSharePermission]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetAppletLaunchFlags ==&lt;br /&gt;
No input, returns an u32 bitmask [[#AppletLaunchFlag]].&lt;br /&gt;
&lt;br /&gt;
== SetAppletLaunchFlags ==&lt;br /&gt;
Takes an input u32 bitmask [[#AppletLaunchFlag]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetKeyboardLayout ==&lt;br /&gt;
No input, returns an output s32 [[#KeyboardLayout]].&lt;br /&gt;
&lt;br /&gt;
== SetKeyboardLayout ==&lt;br /&gt;
Takes an input s32 [[#KeyboardLayout]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetAllowedSslHosts ==&lt;br /&gt;
Takes a type-0x6 output buffer. Returns an output s32 entry count.&lt;br /&gt;
&lt;br /&gt;
== GetRebootlessSystemUpdateVersion ==&lt;br /&gt;
No input, returns an output [[#RebootlessSystemUpdateVersion]].&lt;br /&gt;
&lt;br /&gt;
== GetQuestFlag ==&lt;br /&gt;
Gets a flag determining whether the console is a kiosk unit (codenamed &amp;quot;Quest&amp;quot;). Used by qlaunch to determine whether to launch Retail Interactive Display Menu.&lt;br /&gt;
&lt;br /&gt;
== GetDataDeletionSettings ==&lt;br /&gt;
No input, returns an output [[#DataDeletionSettings]].&lt;br /&gt;
&lt;br /&gt;
== SetDataDeletionSettings ==&lt;br /&gt;
Takes an input [[#DataDeletionSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetWirelessCertificationFileSize ==&lt;br /&gt;
No input, returns an output u64 size.&lt;br /&gt;
&lt;br /&gt;
== GetWirelessCertificationFile ==&lt;br /&gt;
Takes a type-0x6 output buffer, returns an output u64 size.&lt;br /&gt;
&lt;br /&gt;
This gets the [[Flash_Filesystem#PRODINFOF|WirelessCertificationFile]].&lt;br /&gt;
&lt;br /&gt;
== SetRegionCode ==&lt;br /&gt;
Takes an input s32 [[#RegionCode_2|RegionCode]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetChineseTraditionalInputMethod ==&lt;br /&gt;
No input, returns an output s32 [[#ChineseTraditionalInputMethod]].&lt;br /&gt;
&lt;br /&gt;
== SetChineseTraditionalInputMethod ==&lt;br /&gt;
Takes an input s32 [[#ChineseTraditionalInputMethod]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetHomeMenuScheme ==&lt;br /&gt;
No input. Returns an output [[#HomeMenuScheme]].&lt;br /&gt;
&lt;br /&gt;
The colors are loaded from [[Calibration]], with the set of fields to use selected by [[Calibration#ColorVariation|ColorVariation]].&lt;br /&gt;
&lt;br /&gt;
== GetT ==&lt;br /&gt;
No input, returns an output u8 bool &#039;&#039;&#039;IsT&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[9.0.0+] This is a wrapper for [[#GetPlatformRegion]]: &amp;lt;code&amp;gt;IsT = (PlatformRegion == 2)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== SetT ==&lt;br /&gt;
Takes an input u8 bool &#039;&#039;&#039;IsT&#039;&#039;&#039;, no output.&lt;br /&gt;
&lt;br /&gt;
[9.0.0+] This is a wrapper for [[#SetPlatformRegion]]: &amp;lt;code&amp;gt;PlatformRegion = 1 + (IsT &amp;amp; 1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== GetPlatformRegion ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetPlatformRegion ==&lt;br /&gt;
Takes an input s32, no output.&lt;br /&gt;
&lt;br /&gt;
== GetHomeMenuSchemeModel ==&lt;br /&gt;
No input. Returns an output u32.&lt;br /&gt;
&lt;br /&gt;
Loads the 0xB-byte setting &amp;lt;&amp;quot;settings_debug&amp;quot;, &amp;quot;home_menu_scheme_model&amp;quot;&amp;gt;, throwing an error if loading this fails. Depending on the content of the setting, the output u32 is either determined by the value of this setting, or loaded from [[Calibration#ColorModel|ColorModel]].&lt;br /&gt;
&lt;br /&gt;
== GetMemoryUsageRateFlag ==&lt;br /&gt;
No input, returns an output u8 bool.&lt;br /&gt;
&lt;br /&gt;
== GetTouchScreenMode ==&lt;br /&gt;
No input, returns an output s32.&lt;br /&gt;
&lt;br /&gt;
Official sw loads the output as an u8 and copies it to an output [[#TouchScreenMode]].&lt;br /&gt;
&lt;br /&gt;
== SetTouchScreenMode ==&lt;br /&gt;
Takes an input s32, no output.&lt;br /&gt;
&lt;br /&gt;
Official sw sets the input to an u8 loaded from an input [[#TouchScreenMode]].&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigSettingsFull ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigSettingsFull ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigSettingsEmbedded ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigSettingsEmbedded ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigSettingsLeft ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigSettingsLeft ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigSettingsRight ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigSettingsRight ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigRegisteredSettingsEmbedded ==&lt;br /&gt;
Takes a type-0x16 output buffer containing a [[#ButtonConfigRegisteredSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigRegisteredSettingsEmbedded ==&lt;br /&gt;
Takes a type-0x15 input buffer containing a [[#ButtonConfigRegisteredSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetButtonConfigRegisteredSettings ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an array of [[#ButtonConfigRegisteredSettings]], returns an output s32.&lt;br /&gt;
&lt;br /&gt;
== SetButtonConfigRegisteredSettings ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an array of [[#ButtonConfigRegisteredSettings]], no output.&lt;br /&gt;
&lt;br /&gt;
== GetFieldTestingFlag ==&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
== SetFieldTestingFlag ==&lt;br /&gt;
Takes an input bool, no output.&lt;br /&gt;
&lt;br /&gt;
== GetTextMagnificationRatio ==&lt;br /&gt;
This is exclusive to S2.&lt;br /&gt;
&lt;br /&gt;
No input, returns an output float.&lt;br /&gt;
&lt;br /&gt;
== ConvertToProductModel ==&lt;br /&gt;
Takes an input [[#ProductModelName|ProductModelName]], returns an output [[#ProductModel|ProductModel]].&lt;br /&gt;
&lt;br /&gt;
== ConvertToProductModelName ==&lt;br /&gt;
Takes an input [[#ProductModel|ProductModel]], return an output [[#ProductModelName|ProductModelName]].&lt;br /&gt;
&lt;br /&gt;
When the input [[#ProductModel|ProductModel]] is invalid, this writes 0 to output and returns 0.&lt;br /&gt;
&lt;br /&gt;
= Language =&lt;br /&gt;
This is &amp;quot;nn::settings::Language&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Japanese&lt;br /&gt;
|-&lt;br /&gt;
| 1 || AmericanEnglish&lt;br /&gt;
|-&lt;br /&gt;
| 2 || French&lt;br /&gt;
|-&lt;br /&gt;
| 3 || German&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Italian&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Spanish&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Chinese&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Korean&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Dutch&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Portuguese&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Russian&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Taiwanese&lt;br /&gt;
|-&lt;br /&gt;
| 12 || BritishEnglish&lt;br /&gt;
|-&lt;br /&gt;
| 13 || CanadianFrench&lt;br /&gt;
|-&lt;br /&gt;
| 14 || LatinAmericanSpanish&lt;br /&gt;
|-&lt;br /&gt;
| 15 || [4.0.0+] SimplifiedChinese&lt;br /&gt;
|-&lt;br /&gt;
| 16 || [4.0.0+] TraditionalChinese&lt;br /&gt;
|-&lt;br /&gt;
| 17 || [10.1.0+] BrazilianPortuguese&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= LanguageCode =&lt;br /&gt;
This is &amp;quot;nn::settings::LanguageCode&amp;quot;. This is an u64, which is a NUL-terminated string.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || [[#Language]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ja&amp;quot; || Japanese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;en-US&amp;quot; || AmericanEnglish&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;fr&amp;quot; || French&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;de&amp;quot; || German&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;it&amp;quot; || Italian&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;es&amp;quot; || Spanish&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;zh-CN&amp;quot; || Chinese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ko&amp;quot; || Korean&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;nl&amp;quot; || Dutch&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;pt&amp;quot; || Portuguese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ru&amp;quot; || Russian&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;zh-TW&amp;quot; || Taiwanese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;en-GB&amp;quot; || BritishEnglish&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;fr-CA&amp;quot; || CanadianFrench&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;es-419&amp;quot; || LatinAmericanSpanish&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;zh-Hans&amp;quot; || [4.0.0+] SimplifiedChinese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;zh-Hant&amp;quot; || [4.0.0+] TraditionalChinese&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;pt-BR&amp;quot; || [10.1.0+] BrazilianPortuguese&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AccelerometerOffset =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AccelerometerOffset&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || X&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || Z&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AccelerometerScale =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AccelerometerScale&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || X&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || Z&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcdsaCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcdsaCertificate&amp;quot;. This is a 0x70-byte struct.&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcqvBlsCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcqvBlsCertificate&amp;quot;. This is a 0x20-byte struct.&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcqvBlsKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcqvBlsKey&amp;quot;. This is a 0x40-byte struct.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x40 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x40 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcqvBlsRootCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcqvBlsRootCertificate&amp;quot;. This is a 0x90-byte struct.&lt;br /&gt;
&lt;br /&gt;
= AmiiboEcqvCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboEcqvCertificate&amp;quot;. This is a 0x14-byte struct.&lt;br /&gt;
&lt;br /&gt;
= AmiiboKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AmiiboKey&amp;quot;. This is a 0x50-byte struct.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x50 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AnalogStickFactoryCalibration =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AnalogStickFactoryCalibration&amp;quot;. Same as [[Calibration#AnalogStickFactoryCalibration|AnalogStickFactoryCalibration]].&lt;br /&gt;
&lt;br /&gt;
= AnalogStickModelParameter =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::AnalogStickModelParameter&amp;quot;. Same as [[Calibration#AnalogStickModelParameter|AnalogStickModelParameter]].&lt;br /&gt;
&lt;br /&gt;
= BatteryLot =&lt;br /&gt;
This is &amp;quot;nn::settings::BatteryLot&amp;quot;. This is a 0x18-byte struct.&lt;br /&gt;
&lt;br /&gt;
= BdAddress =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::BdAddress&amp;quot;. This is a 0x6-byte struct.&lt;br /&gt;
&lt;br /&gt;
= ConfigurationId1 =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::ConfigurationId1&amp;quot;. This is a 0x1E-byte struct.&lt;br /&gt;
&lt;br /&gt;
Usually, this is a string with the following format:&lt;br /&gt;
  {EventType}_{ProductModelType}_{MajorVersion}_{MinorVersion}_{MicroVersion}&lt;br /&gt;
&lt;br /&gt;
== EventType ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;FP&amp;quot; || Functional prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;EP&amp;quot; || Engineering prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;DP&amp;quot; || Design prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;DPRD&amp;quot; || Design prototype for R&amp;amp;D&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HOAG&amp;quot; || Hoag prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;COPPER&amp;quot; || Copper prototype&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;EDEV&amp;quot; || Extcon development kit for Icosa and Iowa&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;SDEV&amp;quot; || SPI development kit for Icosa and Iowa&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;MEDEV&amp;quot; || Mariko EDEV (deprecated)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;MSDEV&amp;quot; || Mariko SDEV (deprecated)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HDEV&amp;quot; || Development kit for Hoag&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ADEV&amp;quot; || Development kit for Aula&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;MP&amp;quot; || Mass production (retail Icosa)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;MNX&amp;quot; || Mariko NX (retail Iowa)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HNX&amp;quot; || Hoag NX (retail Hoag)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;ANX&amp;quot; || Aula NX (retail Aula)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ProductModelType ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;00&amp;quot; || Icosa&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;01&amp;quot; || Iowa (previously Copper)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;02&amp;quot; || Hoag&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;03&amp;quot; || Calcio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;04&amp;quot; || Aula&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ConsoleSixAxisSensorHorizontalOffset =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::ConsoleSixAxisSensorHorizontalOffset&amp;quot;. Same as [[Calibration#ConsoleSixAxisSensorHorizontalOffset|ConsoleSixAxisSensorHorizontalOffset]].&lt;br /&gt;
&lt;br /&gt;
= CountryCode =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::CountryCode&amp;quot;. This is a 0x3-byte struct.&lt;br /&gt;
&lt;br /&gt;
= EccB233DeviceCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::EccB233DeviceCertificate&amp;quot;. This is a 0x180-byte struct.&lt;br /&gt;
&lt;br /&gt;
= EccB233DeviceKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::EccB233DeviceKey&amp;quot;. This is a 0x30-byte struct or a 0x54-byte struct in the extended version.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x54 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= GameCardCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::GameCardCertificate&amp;quot;. This is a 0x400-byte struct.&lt;br /&gt;
&lt;br /&gt;
= GameCardKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::GameCardKey&amp;quot;. This is a 0x110-byte struct or a 0x130-byte struct in the extended version.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x130 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= GyroscopeOffset =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::GyroscopeOffset&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || X&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || Z&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= GyroscopeScale =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::GyroscopeScale&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || X&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || Z&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= MacAddress =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::MacAddress&amp;quot;. This is a 0x6-byte struct.&lt;br /&gt;
&lt;br /&gt;
= Rsa2048DeviceCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::Rsa2048DeviceCertificate&amp;quot;. This is a 0x240-byte struct.&lt;br /&gt;
&lt;br /&gt;
= Rsa2048DeviceKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::Rsa2048DeviceKey&amp;quot;. This is a 0x220-byte struct or a 0x240-byte struct in the extended version.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x240 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x240 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SerialNumber =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::SerialNumber&amp;quot;. This is a 0x18-byte struct.&lt;br /&gt;
&lt;br /&gt;
= SpeakerParameter =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::SpeakerParameter&amp;quot;. This is copied from the first 0x5A bytes of [[Calibration#SpeakerCalibrationValue|SpeakerCalibrationValue]].&lt;br /&gt;
&lt;br /&gt;
= SslCertificate =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::SslCertificate&amp;quot;. This is a 0x804-byte struct.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || Variable || Data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SslKey =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::SslKey&amp;quot;. This is a 0x110-byte struct or a 0x130-byte struct in the extended version.&lt;br /&gt;
&lt;br /&gt;
If [[Calibration#CAL0|Calibration Version]] &amp;gt;= 9, this is now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x130 || Key&lt;br /&gt;
|-&lt;br /&gt;
| 0x130 || 0x4 || KeyGeneration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= RegionCode =&lt;br /&gt;
This is &amp;quot;nn::settings::factory::RegionCode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Japan&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Usa&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Europe&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Australia&lt;br /&gt;
|-&lt;br /&gt;
| 4 || China&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Korea&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Taiwan&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AudioOutputMode =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AudioOutputMode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1ch&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2ch&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 5_1ch&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 7_1ch&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AudioOutputModeTarget =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AudioOutputModeTarget&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Hdmi&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Speaker&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Headphone&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AudioVolumeTarget =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AudioVolumeTarget&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Speaker&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Headphone&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= DeviceNickName =&lt;br /&gt;
This is &amp;quot;nn::settings::system::DeviceNickName&amp;quot;. This is a 0x80-byte struct.&lt;br /&gt;
&lt;br /&gt;
= Edid =&lt;br /&gt;
This is &amp;quot;nn::settings::system::Edid&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x80 || Data0&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || 0x80 || Data1&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x80 || [13.0.0+] Data2&lt;br /&gt;
|-&lt;br /&gt;
| 0x180 || 0x80 || [13.0.0+] Data3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= RegionCode =&lt;br /&gt;
This is &amp;quot;nn::settings::system::RegionCode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Japan&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Usa&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Europe&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Australia&lt;br /&gt;
|-&lt;br /&gt;
| 4 || HongKongTaiwanKorea&lt;br /&gt;
|-&lt;br /&gt;
| 5 || China&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UserSelectorFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::UserSelectorFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || SkipsIfSingleUser&lt;br /&gt;
|-&lt;br /&gt;
| 31 || Unknown&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UserSelectorSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::UserSelectorSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This contains an u32 bitmask for [[#UserSelectorFlag]].&lt;br /&gt;
&lt;br /&gt;
= AccountSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AccountSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This contains [[#UserSelectorSettings]].&lt;br /&gt;
&lt;br /&gt;
= ClockSourceId =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ClockSourceId&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || NetworkSystemClock&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SteadyClock&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NotificationVolume =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NotificationVolume&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Mute&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Low&lt;br /&gt;
|-&lt;br /&gt;
| 2 || High&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= FriendPresenceOverlayPermission =&lt;br /&gt;
This is &amp;quot;nn::settings::system::FriendPresenceOverlayPermission&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || NotConfirmed&lt;br /&gt;
|-&lt;br /&gt;
| 1 || NoDisplay&lt;br /&gt;
|-&lt;br /&gt;
| 2 || FavoriteFriends&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Friends&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= TvResolution =&lt;br /&gt;
This is &amp;quot;nn::settings::system::TvResolution&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Auto&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 1080p&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 720p&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 480p&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= HdmiContentType =&lt;br /&gt;
This is &amp;quot;nn::settings::system::HdmiContentType&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || None&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Graphics&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Cinema&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Photo&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Game&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= RgbRange =&lt;br /&gt;
This is &amp;quot;nn::settings::system::RgbRange&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Auto&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Full&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Limited&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= CmuMode =&lt;br /&gt;
This is &amp;quot;nn::settings::system::CmuMode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || None&lt;br /&gt;
|-&lt;br /&gt;
| 1 || ColorInvert&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HighContrast&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GrayScale&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= HandheldSleepPlan =&lt;br /&gt;
This is &amp;quot;nn::settings::system::HandheldSleepPlan&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1Min&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 3Min&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 5Min&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 10Min&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 30Min&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Never&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ConsoleSleepPlan =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ConsoleSleepPlan&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1Hour&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2Hour&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 3Hour&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 6Hour&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 12Hour&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Never&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= EulaVersion =&lt;br /&gt;
This is &amp;quot;nn::settings::system::EulaVersion&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Version&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || [[#RegionCode_2|RegionCode]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || [[#SteadyClockSourceId|ClockType]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || [[Glue_services#PosixTime|NetworkSystemClock]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x18 || [[Glue_services#SteadyClockTimePoint|SteadyClock]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= FirmwareVersion =&lt;br /&gt;
This is &amp;quot;nn::settings::system::FirmwareVersion&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || Major&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || Minor&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x1 || Micro&lt;br /&gt;
|-&lt;br /&gt;
| 0x3 || 0x1 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || ReleaseNumber&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Platform&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x40 || Revision&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x18 || DisplayVersion&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || 0x80 || DisplayName&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= PtmFuelGaugeParameter =&lt;br /&gt;
This is &amp;quot;nn::settings::system::PtmFuelGaugeParameter&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x2 || Rcomp0&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || TempCo&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || FullCap&lt;br /&gt;
|-&lt;br /&gt;
| 0x6 || 0x2 || FullCapNom&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x2 || IavgEmpty&lt;br /&gt;
|-&lt;br /&gt;
| 0xA || 0x2 || QrTable00&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x2 || QrTable10&lt;br /&gt;
|-&lt;br /&gt;
| 0xE || 0x2 || QrTable20&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x2 || QrTable30&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || 0x2 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 0x4 || Cycles&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SecuritySettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::SecuritySettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || AuthenticationMode&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || EncryptionMode&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x40 || KeyMaterial&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x4 || KeyMaterialLength&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NotificationTime =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NotificationTime&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Hour&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || Minute&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NotificationFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NotificationFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || RingtoneFlag&lt;br /&gt;
|-&lt;br /&gt;
| 1 || DownloadCompletionFlag&lt;br /&gt;
|-&lt;br /&gt;
| 8 || EnablesNews&lt;br /&gt;
|-&lt;br /&gt;
| 9 || IncomingLampFlag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NotificationSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NotificationSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#NotificationFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || [[#NotificationVolume|Volume]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || [[#NotificationTime|HeadTime]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || [[#NotificationTime|TailTime]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AccountNotificationFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AccountNotificationFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || FriendOnlineFlag&lt;br /&gt;
|-&lt;br /&gt;
| 1 || FriendRequestFlag&lt;br /&gt;
|-&lt;br /&gt;
| 8 || CoralInvitationFlag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AccountNotificationSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AccountNotificationSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || [[Account_services#Uid|Uid]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x4 || [[#AccountNotificationFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 0x1 || [[#FriendPresenceOverlayPermission|FriendPresenceOverlayPermission]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x15 || 0x1 || [[#FriendPresenceOverlayPermission|FriendInvitationOverlayPermission]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x16 || 0x2 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= TvFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::TvFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Allows4k&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Allows3d&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AllowsCec&lt;br /&gt;
|-&lt;br /&gt;
| 3 || PreventsScreenBurnIn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= TvSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::TvSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#TvFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || [[#TvResolution|TvResolution]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || [[#HdmiContentType|HdmiContentType]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || [[#RgbRange|RgbRange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x4 || [[#CmuMode|CmuMode]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 0x4 || TvUnderscan&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x4 || TvGamma&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x4 || ContrastRatio&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= DataDeletionFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::DataDeletionFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || AutomaticDeletionFlag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= DataDeletionSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::DataDeletionSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#DataDeletionFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || UseCount&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SleepFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::SleepFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || SleepsWhilePlayingMedia&lt;br /&gt;
|-&lt;br /&gt;
| 1 || WakesAtPowerStateChange&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SleepSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::SleepSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#SleepFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || [[#HandheldSleepPlan|HandheldSleepPlan]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || [[#ConsoleSleepPlan|ConsoleSleepPlan]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= InitialLaunchFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::InitialLaunchFlag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || InitialLaunchCompletionFlag&lt;br /&gt;
|-&lt;br /&gt;
| 8 || InitialLaunchUserAdditionFlag&lt;br /&gt;
|-&lt;br /&gt;
| 16 || InitialLaunchTimestampFlag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= InitialLaunchSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::InitialLaunchSettings&amp;quot;. This struct is 8-byte aligned.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || [[#InitialLaunchFlag|Flags]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x18 || [[Glue_services#SteadyClockTimePoint|TimeStamp]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= RebootlessSystemUpdateVersion =&lt;br /&gt;
This is &amp;quot;nn::settings::system::RebootlessSystemUpdateVersion&amp;quot;. This struct is 4-byte aligned.&lt;br /&gt;
&lt;br /&gt;
This is the content of the RebootlessSystemUpdateVersion SystemData, in the &amp;quot;/version&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Version&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x1C || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || DisplayVersion&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= PrimaryAlbumStorage =&lt;br /&gt;
This is &amp;quot;nn::settings::system::PrimaryAlbumStorage&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Nand&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SdCard&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ErrorReportSharePermission =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ErrorReportSharePermission&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || NotConfirmed&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Granted&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Denied&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ServiceDiscoveryControlSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ServiceDiscoveryControlSettings&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Bits&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| IsChangeEnvironmentIdentifierDisabled&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= AppletLaunchFlag =&lt;br /&gt;
This is &amp;quot;nn::settings::system::AppletLaunchFlag&amp;quot;. This is an u32 bitmask.&lt;br /&gt;
&lt;br /&gt;
= KeyboardLayout =&lt;br /&gt;
This is &amp;quot;nn::settings::KeyboardLayout&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || EnglishUs&lt;br /&gt;
|-&lt;br /&gt;
| 2 || EnglishUsInternational&lt;br /&gt;
|-&lt;br /&gt;
| 3 || EnglishUk&lt;br /&gt;
|-&lt;br /&gt;
| 4 || French&lt;br /&gt;
|-&lt;br /&gt;
| 5 || FrenchCa&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Spanish&lt;br /&gt;
|-&lt;br /&gt;
| 7 || SpanishLatin&lt;br /&gt;
|-&lt;br /&gt;
| 8 || German&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Italian&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Portuguese&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Russian&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Korean&lt;br /&gt;
|-&lt;br /&gt;
| 13 || ChineseSimplified&lt;br /&gt;
|-&lt;br /&gt;
| 14 || ChineseTraditional&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ChineseTraditionalInputMethod =&lt;br /&gt;
This is &amp;quot;nn::settings::ChineseTraditionalInputMethod&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= HomeMenuScheme =&lt;br /&gt;
This is &amp;quot;nn::settings::system::HomeMenuScheme&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || MainColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || BackColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || SubColor&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x4 || BezelColor&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= TouchScreenMode =&lt;br /&gt;
This is &amp;quot;nn::settings::system::TouchScreenMode&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Stylus&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Standard&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ButtonConfigSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ButtonConfigSettings&amp;quot;. This is a 0x5A8-byte struct.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || IsFull bool flag. 0 = empty config, 1 = config set. Also accessed as an u32, but only bit0 is used.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x3 || Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x1C4 || Unused&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C8 || 0x3E0 || Config&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ButtonConfigRegisteredSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ButtonConfigRegisteredSettings&amp;quot;. This is a 0x5C8-byte struct.&lt;br /&gt;
&lt;br /&gt;
= BluetoothDevicesSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::BluetoothDevicesSettings&amp;quot;. This is a 0x200-byte struct.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x6 || [[BTM_services#BdAddress|BdAddr]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x6 || 0x20 || [13.0.0+] Reserved ([1.0.0-12.1.0] [[BTM_services#BdName|DeviceName]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x26 || 0x3 || [[BTM_services#ClassOfDevice|ClassOfDevice]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x29 || 0x10 || LinkKey&lt;br /&gt;
|-&lt;br /&gt;
| 0x39 || 0x1 || LinkKeyPresent&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A || 0x2 || Version&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C || 0x4 || TrustedServices&lt;br /&gt;
|-&lt;br /&gt;
| 0x40 || 0x2 || Vid&lt;br /&gt;
|-&lt;br /&gt;
| 0x42 || 0x2 || Pid&lt;br /&gt;
|-&lt;br /&gt;
| 0x44 || 0x1 || SubClass&lt;br /&gt;
|-&lt;br /&gt;
| 0x45 || 0x1 || AttributeMask&lt;br /&gt;
|-&lt;br /&gt;
| 0x46 || 0x2 || DescriptorLength&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x80 || Descriptor&lt;br /&gt;
|-&lt;br /&gt;
| 0xC8 || 0x1 || KeyType&lt;br /&gt;
|-&lt;br /&gt;
| 0xC9 || 0x1 || DeviceType&lt;br /&gt;
|-&lt;br /&gt;
| 0xCA || 0x2 || BrrSize&lt;br /&gt;
|-&lt;br /&gt;
| 0xCC || 0x9 || Brr&lt;br /&gt;
|-&lt;br /&gt;
| 0xD5 || 0x1 || [13.0.0+] AudioSourceVolume&lt;br /&gt;
|-&lt;br /&gt;
| 0xD6 || 0xF9 || [13.0.0+] DeviceName&lt;br /&gt;
|-&lt;br /&gt;
| 0x1CF || 0x1 || [15.0.0+] AudioSinkVolume&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D0 || 0x4 || [14.0.0+] AudioFlags&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D4 || 0x2C || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= NxControllerLegacySettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NxControllerLegacySettings&amp;quot; ([1.0.0-12.1.0] &amp;quot;nn::settings::system::NxControllerSettings&amp;quot;). This is a 0x29-byte struct.&lt;br /&gt;
&lt;br /&gt;
= NxControllerSettings =&lt;br /&gt;
This is &amp;quot;nn::settings::system::NxControllerSettings&amp;quot;. This is a 0x42C-byte struct. This was added with [13.0.0+].&lt;br /&gt;
&lt;br /&gt;
= ProductModel =&lt;br /&gt;
Ths is &amp;quot;nn::settings::system::ProductModel&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! [[#ProductModelName|ProductModelName]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || &amp;quot;HAC&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 3 || &amp;quot;HAD&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 4 || &amp;quot;HDH&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 6 || &amp;quot;HEG&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 7 || &amp;quot;BEE&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= ProductModelName =&lt;br /&gt;
This is &amp;quot;nn::settings::system::ProductModelName&amp;quot;. This is a 0x8-byte struct containing a [[#ProductModel|string]].&lt;br /&gt;
&lt;br /&gt;
= System Configuration =&lt;br /&gt;
There&#039;s a common configuration title (*818), and one configuration title for each [[SMC#HardwareType|HardwareType]].&lt;br /&gt;
&lt;br /&gt;
See [[System_Settings]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14634</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14634"/>
		<updated>2026-04-30T05:18:14Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* WaitConnectionAsync */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them ([[#Data|Data]] messages not allowed), and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3 (any network message besides [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from +0x100 in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#SendClientProfile|SendClientProfile]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends [[#RequestServerProfile|RequestServerProfile]], then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14633</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14633"/>
		<updated>2026-04-30T05:02:42Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them, and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3. The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from +0x100 in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#SendClientProfile|SendClientProfile]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends [[#RequestServerProfile|RequestServerProfile]], then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14632</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14632"/>
		<updated>2026-04-30T04:58:04Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them, and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3. The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being the [[#AdvertiseData|Uuid]].&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from +0x100 in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#SendClientProfile|SendClientProfile]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends [[#RequestServerProfile|RequestServerProfile]], then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Immediately after a socket connection is setup, the AdvertiseData is set to size=0. Later when the server recreates the network it also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14631</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14631"/>
		<updated>2026-04-30T01:59:28Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* 0x12 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them, and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3. The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being 0x10-bytes.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from +0x100 in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#SendClientProfile|SendClientProfile]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends [[#RequestServerProfile|RequestServerProfile]], then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || Data size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || {Above size} || Data payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14630</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14630"/>
		<updated>2026-04-30T00:55:27Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them, and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#RequestServerProfile|RequestServerProfile]] and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#RequestServerProfile|RequestServerProfile]] handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3. The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from earlier, with the input AdvertiseData being 0x10-bytes.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from +0x100 in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#SendClientProfile|SendClientProfile]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends [[#RequestServerProfile|RequestServerProfile]], then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#RequestServerProfile|RequestServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== RequestServerProfile ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload (0x148-byte struct, which has the following layout):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Zeros&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x11C || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x120 || 0x24 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x144 || 0x4 || Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following [[#RequestServerProfile|RequestServerProfile]], where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14629</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14629"/>
		<updated>2026-04-29T22:29:35Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them, and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#SendClientProfile|SendClientProfile]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#Data|Data]] message 0x10 and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#Data|Data]] message 0x10 handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3. The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from eariler, with the input AdvertiseData being 0x10-bytes.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state. This originates from +0x100 in the [[#SendClientProfile|SendClientProfile]] request.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#SendClientProfile|SendClientProfile]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#SendClientProfile|SendClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#SendClientProfile|SendClientProfile]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== SendClientProfile ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14628</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14628"/>
		<updated>2026-04-29T21:38:28Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* PrepareTransferDisconnect */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them, and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#ClientProfileNetwork|ClientProfileNetwork]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#Data|Data]] message 0x10 and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#Data|Data]] message 0x10 handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3. The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from eariler, with the input AdvertiseData being 0x10-bytes.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14627</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14627"/>
		<updated>2026-04-29T17:34:48Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3 (network message [[#Initialize|Initialize]]/[[#Initialize|Initialize2]] handled). Two funcs are called repeatedly in this loop. These essentially receive [[#Messages|messages]] + process them, and send the response network message.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* Calls a vfunc. When the ret is true:&lt;br /&gt;
** Calls a func, which receives [[#ClientProfileNetwork|ClientProfileNetwork]] and sends the response. Also calls a func to process the received data.&lt;br /&gt;
** Receives [[#Data|Data]] message 0x10 and sends the response.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func identical to the first network-message func called in the above block, except a different func is called at the end.&lt;br /&gt;
** Runs the same [[#Data|Data]] message 0x10 handling as above.&lt;br /&gt;
** Calls a func. This calls a func, then receives [[#Data|Data]] message 0x12 and sends the response.&lt;br /&gt;
** Calls a func. This runs functionality similar to the eariler message-loop, except this waits for the state field to change to !=0x3. The socket is closed, then a func is called which handles [[LDN_services|ldn]] + [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially calls the network-creation func from eariler, with the input AdvertiseData being 0x10-bytes.&lt;br /&gt;
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.&lt;br /&gt;
* Updates a state flag and returns 0.&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14626</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14626"/>
		<updated>2026-04-29T04:03:43Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* Messages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the 0x20-bytes which is used for [[#KeyExchange|KeyExchange]] response_plaintext+0x48.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14625</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14625"/>
		<updated>2026-04-29T03:43:50Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14624</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14624"/>
		<updated>2026-04-29T03:12:32Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation (generated with [[SPL_services|GenerateRandomBytes]]).&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]]. Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14622</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14622"/>
		<updated>2026-04-27T21:40:38Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* AcceptDecline */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14621</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14621"/>
		<updated>2026-04-27T21:37:35Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd220 ===&lt;br /&gt;
No input, returns a 0x10-byte struct.&lt;br /&gt;
&lt;br /&gt;
This gets the 0x10-byte struct in state, which was received by [[#WaitAcceptanceAsync|WaitAcceptanceAsync]] from [[#AcceptDecline|AcceptDecline]] (originates from [[#DeclineAsync2|DeclineAsync2]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14620</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14620"/>
		<updated>2026-04-27T21:15:03Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] [[#WaitAcceptanceAsync|WaitAcceptanceAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== WaitAcceptanceAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially (after state validation) just calls a func which handles receiving + responding to a network message ([[#AcceptDecline|AcceptDecline]] or [[#Suspend|Suspend]]).&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14619</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14619"/>
		<updated>2026-04-26T21:19:48Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* IClient */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] WaitAcceptanceAsync&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
When the [[#ConnectByServerIdAsync|connected]] state flag is set, this runs code similar to [[#SuspendAsync|SuspendAsync]], without the network message. Then various vfuncs are called. Various funcs are also called as needed (fs related?).&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14617</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14617"/>
		<updated>2026-04-26T18:51:56Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* IClient */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] WaitAcceptanceAsync&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] [[#Abort|Abort]]&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+] [[#AbortAsync|AbortAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== Abort ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
=== AbortAsync ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
On 19.x the async task is the cmd impl func used by [[#Abort|Abort]].&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14616</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14616"/>
		<updated>2026-04-26T16:36:22Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] WaitAcceptanceAsync&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== SuspendAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task essentially just verifies the [[#ConnectByServerIdAsync|connected]] state flag is set, uses network message [[#Suspend|Suspend]], closes the socket, calls the func which closes [[LDN_services|ldn]] + [[Sockets_services|sockets]], then clears the connected state flag.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Suspend|Suspend]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== TransferNext ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== SynchronizeState ====&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== Suspend ====&lt;br /&gt;
The client sends this via [[#SuspendAsync|SuspendAsync]]&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14615</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14615"/>
		<updated>2026-04-26T15:44:15Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* TransferNextAsync */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] WaitAcceptanceAsync&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an earlier func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== PrepareTransferDisconnect ===&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
=== PrepareTransfer ===&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== TransferNext ===&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
=== SynchronizeState ===&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14608</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14608"/>
		<updated>2026-04-26T03:25:18Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] WaitAcceptanceAsync&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This uses network message [[#SynchronizeState|SynchronizeState]] with value 1. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called: (this flag is usually set?)&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an eariler func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== PrepareTransferDisconnect ===&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
=== PrepareTransfer ===&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== TransferNext ===&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
=== SynchronizeState ===&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14607</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14607"/>
		<updated>2026-04-26T03:18:04Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Migration is a sysmodule designed for handling the Switch-to-Switch transfer system introduced in firmware [[4.0.0]].&lt;br /&gt;
&lt;br /&gt;
With newer system-versions this sysmodule is only running when [[qlaunch]] is using migration from the relevant transfer menus (see [[Applet_Manager_services#ActivateMigrationService|ActivateMigrationService]]/[[Applet_Manager_services#DeactivateMigrationService|DeactivateMigrationService]]).&lt;br /&gt;
&lt;br /&gt;
= mig:usr =&lt;br /&gt;
This is &amp;quot;nn::migration::user::IService&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [7.0.0-19.0.1] TryGetLastUserMigrationInfo ([4.0.0-6.2.0] TryGetLastMigrationInfo)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [7.0.0+] [[#CreateUserMigrationServer|CreateUserMigrationServer]] ([4.0.0-6.2.0] CreateServer)&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [7.0.0+] [[#ResumeUserMigrationServer|ResumeUserMigrationServer]] ([4.0.0-6.2.0] ResumeServer)&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [7.0.0+] [[#CreateUserMigrationClient|CreateUserMigrationClient]] ([4.0.0-6.2.0] CreateClient)&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo&lt;br /&gt;
|-&lt;br /&gt;
| 1100 || [7.0.0-19.0.1] [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1101 || [7.0.0+] [[#ResumeSaveDataMigrationServer|ResumeSaveDataMigrationServer]]&lt;br /&gt;
|-&lt;br /&gt;
| 1110 || [17.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 1200 || [7.0.0+] [[#CreateSaveDataMigrationClient|CreateSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 1201 || [7.0.0+] [[#ResumeSaveDataMigrationClient|ResumeSaveDataMigrationClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2010 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2100 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2110 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2200 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2210 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2220 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2221 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2230 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2231 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2232 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2233 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2234 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2250 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2260 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2270 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2280 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2300 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2310 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2400 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 2420 || [20.0.0+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationServer ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer]].&lt;br /&gt;
&lt;br /&gt;
== CreateUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeUserMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient]].&lt;br /&gt;
&lt;br /&gt;
== GetSaveDataMigrationPolicyInfoAsync ==&lt;br /&gt;
Takes an [[NCM_services#ApplicationId|ApplicationId]], returns an [[#IAsyncSaveDataMigrationPolicyInfoContext]].&lt;br /&gt;
&lt;br /&gt;
This is used by [[qlaunch]] before the actual savedata transfer is started.&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|save_data_migration_policy]].&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] This was stubbed. The network request is no longer done and the various [[#IAsyncSaveDataMigrationPolicyInfoContext|IAsyncSaveDataMigrationPolicyInfoContext]] cmds just return success (besides GetSystemEvent). GetSaveDataMigrationPolicyInfo just returns the data which was set during object creation.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationServer ==&lt;br /&gt;
Takes a total of 0x20-bytes of input, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationServer ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd1110 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a type-0x19 input buffer, a type-0x5 input buffer containing an array of u64s, and a TransferMemory handle. Returns an [[#IServer_2|IServer]].&lt;br /&gt;
&lt;br /&gt;
This is identical to [[#CreateSaveDataMigrationServer|CreateSaveDataMigrationServer]] except the u64-array is passed directly instead of from a single input u64.&lt;br /&gt;
&lt;br /&gt;
== CreateSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a type-0x19 input buffer, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== ResumeSaveDataMigrationClient ==&lt;br /&gt;
Takes an input u32, a TransferMemory handle, returns an [[#IClient_2|IClient]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2100 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2110 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IServer_3|IServer]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2200 ==&lt;br /&gt;
Takes 4-bytes of input, a type-0x19 input buffer containing a 0x100-byte struct, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2210 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IClient_3|IClient]].&lt;br /&gt;
&lt;br /&gt;
On NX this just calls a logging func and returns an error.&lt;br /&gt;
&lt;br /&gt;
== Cmd2250 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2260 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUnknown|IUnknown]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2280 ==&lt;br /&gt;
Takes an input u64, returns an [[#IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This starts a network request for [[Network|transfer_events/%lld/rollback]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2300 ==&lt;br /&gt;
Takes a total of 0x18-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2310 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IUploader|IUploader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2400 ==&lt;br /&gt;
Takes a total of 0x10-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== Cmd2420 ==&lt;br /&gt;
Takes 4-bytes of input, a handle. Returns an [[#IDownloader|IDownloader]].&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IServer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetServerProfile|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || WaitConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || AcceptConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 203 || DeclineConnectionAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::user::IClient&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 10 || CreateLoginSession&lt;br /&gt;
|-&lt;br /&gt;
| 11 || GetNetworkServiceAccountId&lt;br /&gt;
|-&lt;br /&gt;
| 12 || GetUserNickname&lt;br /&gt;
|-&lt;br /&gt;
| 13 || GetUserProfileImage&lt;br /&gt;
|-&lt;br /&gt;
| 100 || PrepareAsync&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || ListServers&lt;br /&gt;
|-&lt;br /&gt;
| 210 || ConnectByServerIdAsync&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 311 || GetCurrentRelatedApplications&lt;br /&gt;
|-&lt;br /&gt;
| 320 || TransferNextAsync&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || Abort&lt;br /&gt;
|-&lt;br /&gt;
| 999 || DebugSynchronizeStateInFinalizationAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IAsyncSaveDataMigrationPolicyInfoContext ==&lt;br /&gt;
This is &amp;quot;nn::migration::detail::IAsyncSaveDataMigrationPolicyInfoContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetSystemEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Cancel&lt;br /&gt;
|-&lt;br /&gt;
| 2 || HasDone&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetResult&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetSaveDataMigrationPolicyInfo&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetUid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [7.0.0-19.0.1] GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetServerProfile_2|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 100 || [[#PrepareAsync|PrepareAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 102 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 201 || GetClientProfile&lt;br /&gt;
|-&lt;br /&gt;
| 202 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 203 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 204 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [8.0.0+] WaitAcceptanceAsync&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== PrepareAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various other functionality, the async task also uses functionality similar to [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]], throwing an error if needed.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd102 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== WaitConnectionAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
The async task does the following:&lt;br /&gt;
* ...&lt;br /&gt;
* Initializes the data used for the AdvertiseData.&lt;br /&gt;
* Calls a func which:&lt;br /&gt;
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.&lt;br /&gt;
** Calls a func which:&lt;br /&gt;
*** Handles setup for the server socket.&lt;br /&gt;
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.&lt;br /&gt;
*** Waits for a ldn Node to connect, with timeout etc handling.&lt;br /&gt;
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.&lt;br /&gt;
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.&lt;br /&gt;
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).&lt;br /&gt;
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).&lt;br /&gt;
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.&lt;br /&gt;
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.&lt;br /&gt;
** Updates state and returns 0.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
=== Cmd202 ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state.&lt;br /&gt;
&lt;br /&gt;
=== Cmd203 ===&lt;br /&gt;
No input, returns an output s64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with an error being returned when the value is -1.&lt;br /&gt;
&lt;br /&gt;
=== Cmd204 ===&lt;br /&gt;
No input, returns an output u64.&lt;br /&gt;
&lt;br /&gt;
This loads a field from state, with 0 being returned and out=0 when this is -1. Otherwise this is then used as an arrayindex to load the data copied to output.&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::savedata::IClient&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [7.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetClientProfile|GetClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || GetConnectionRequirement&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [20.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 200 || ScanServersAsync&lt;br /&gt;
|-&lt;br /&gt;
| 201 || [[#ListServers|ListServers]]&lt;br /&gt;
|-&lt;br /&gt;
| 210 || [[#ConnectByServerIdAsync|ConnectByServerIdAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 220 || [8.0.0+] [[#AcceptAsync|AcceptAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 221 || [8.0.0-20.5.0] [[#DeclineAsync|DeclineAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 222 || [21.0.0+] [[#DeclineAsync2|DeclineAsync2]]&lt;br /&gt;
|-&lt;br /&gt;
| 300 || GetStorageShortfall&lt;br /&gt;
|-&lt;br /&gt;
| 301 || GetTotalTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 302 || GetImmigrantUid&lt;br /&gt;
|-&lt;br /&gt;
| 303 || GetApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 304 || [17.0.0+] ListApplicationIds&lt;br /&gt;
|-&lt;br /&gt;
| 310 || GetCurrentTransferInfo&lt;br /&gt;
|-&lt;br /&gt;
| 320 || [[#TransferNextAsync|TransferNextAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 350 || SuspendAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || [[#CompleteAsync|CompleteAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 500 || [7.0.0-19.0.1] Abort&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [19.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 996 || [8.0.0+] DebugTryGetState&lt;br /&gt;
|-&lt;br /&gt;
| 997 || [8.0.0+] [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 998 || [8.0.0+] [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]]&lt;br /&gt;
|-&lt;br /&gt;
| 999 || [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetClientProfile ===&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ClientProfile|ClientProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd101 ===&lt;br /&gt;
No input, returns an output bool.&lt;br /&gt;
&lt;br /&gt;
=== ListServers ===&lt;br /&gt;
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.&lt;br /&gt;
&lt;br /&gt;
=== ConnectByServerIdAsync ===&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* ...&lt;br /&gt;
* Loops through an array to find an entry matching the 0x10-bytes from {func input param}, returning an error if not found. (entryptr is the located entry once done)&lt;br /&gt;
* Calls a vfunc. If ret is false:&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
** Calls a func with entryptr+0x20, for copying 0x8-bytes from the input into state.&lt;br /&gt;
** Calls a func with entryptr+0x10, for copying the input 0x10-bytes into state.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
** Clears a state flag if needed.&lt;br /&gt;
** entryptr = { Calls a func which loops through an array to find an entry matching the 0x10-bytes from input. } An error is returned if not found.&lt;br /&gt;
** Copies 0x480-bytes from entryptr+0x10 to stack, which is later passed to the connect-network func below.&lt;br /&gt;
** Calls a func which initializes [[Sockets_services|sockets]] + [[LDN_services|ldn]] if needed (Initialize, SetProtocol(state_field), SetOperationMode(1), OpenStation).&lt;br /&gt;
** Then various funcs are called for socket setup / connecting to the network.&lt;br /&gt;
*** ldn [[LDN_services|Connect]] is used, retrying with timeout as needed.&lt;br /&gt;
*** The TCP socket is setup, and the server is connected to with the IP from the relevant ldn [[LDN_services|NodeInfo]] (GetNetworkInfo) for the AccessPoint.&lt;br /&gt;
** Calls a func. This checks a bool state flag. Each block calls a logging func, a func specific to this block (same params for both), and if this is the flag==false block the flag is then set.&lt;br /&gt;
*** The funcs called from the above flag-block are roughly same. These send a message, handle receiving a message, then send another message + receive a message. For flag==false these are [[#Messages|MessageId]] 0x0/0x1, while for flag==true these are MessageId 0x8/0x9.&lt;br /&gt;
** A func is called which copies 0x10-bytes from entryptr+0x10+0x26C into state.&lt;br /&gt;
* Clears stack. Calls a func.&lt;br /&gt;
* Calls a func. This sends [[#ClientProfileNetwork|ClientProfileNetwork]], then receives network data.&lt;br /&gt;
* Calls a vfunc.&lt;br /&gt;
* When ret is true:&lt;br /&gt;
** Calls a func. This essentially handles sending/receiving network data, etc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
* Otherwise when the vfunc ret is false:&lt;br /&gt;
** Calls a func. This is very similar to the func used in the above block.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
*** Clears stack, and calls a func.&lt;br /&gt;
*** Calls a func which handles sending/receiving network data.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func. This sends a network message with [[#Messages|MessageId]] 0x10, then receives network data. Then the socket is closed. Lastly, a func is called which handles closing [[LDN_services|ldn]] (CloseStation, Finalize) and [[Sockets_services|sockets]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Clears stack. Enters a block which uses nifm.&lt;br /&gt;
*** Calls a func.&lt;br /&gt;
*** Clears stack.&lt;br /&gt;
*** Calls a func to get a state field.&lt;br /&gt;
*** Calls a func which uses network request [[Network|transfer_events/%lld/register_destination]].&lt;br /&gt;
** Nifm usage ends here.&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func which handles [[Sockets_services|sockets]] cleanup.&lt;br /&gt;
** Calls a func. This essentially does ldn setup again / reconnects to the network. The previously mentioned network messages func used after connection is then called here, with the bool flag being previously updated it would now use MessageId 0x8/0x9. State is also updated.&lt;br /&gt;
** Calls a func. This sends data via a [[#Data|Data]] transfer, then receives network data. Afterwards it then calls a vfunc.&lt;br /&gt;
** Sets a state flag, then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== AcceptAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does essentially the following:&lt;br /&gt;
* Validates that the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] is set.&lt;br /&gt;
* Sends [[#AcceptDecline|AcceptDecline]], then receives network data.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task is the same as [[#AcceptAsync|AcceptAsync]] except for the transferred data, and also does the following after the transfer:&lt;br /&gt;
* Closes the socket.&lt;br /&gt;
* Calls the func which handles cleanup for [[LDN_services|ldn]] + [[Sockets_services|sockets]].&lt;br /&gt;
* Clears the state flag which was set at the end of [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], then returns 0.&lt;br /&gt;
&lt;br /&gt;
=== DeclineAsync2 ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes an input 0x10-byte struct, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Same as [[#DeclineAsync|DeclineAsync]] except for the transferred data.&lt;br /&gt;
&lt;br /&gt;
=== TransferNextAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls vfuncs.&lt;br /&gt;
* Calls various funcs to check state. This includes calling a fs-related func?&lt;br /&gt;
* If a state flag is not set, a func is called: (this flag is usually set?)&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect|PrepareTransferDisconnect]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] for header+0x1 match, this just returns.&lt;br /&gt;
** Calls the func which handles disconnecting from the network.&lt;br /&gt;
** Calls two funcs.&lt;br /&gt;
** Calls a func. This handles using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] and uses the relevant [[Filesystem_services|fs]] cmds. [[Filesystem_services|ISaveDataTransferManagerWithDivision SetMode]] is also used with value 1. The previously mentioned state flag is then set.&lt;br /&gt;
** Calls the func which handles reconnecting to the network.&lt;br /&gt;
* Calls a func when a previously loaded state field is 0.&lt;br /&gt;
* Calls a func. (fs related?)&lt;br /&gt;
* Calls a func which validates the output from an eariler func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* Uses network message [[#PrepareTransfer|PrepareTransfer]]. Uses [[Filesystem_services|ISaveDataTransferManagerWithDivision SetLocalKeySeedPackage]] with the relevant response data.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. &amp;quot;tr_size&amp;quot; is logged by adding two u64 fields from the 0x20-byte struct returned by [[#PrepareTransfer|PrepareTransfer]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Calls a func for getting state data.&lt;br /&gt;
* Calls a func which writes the various input to the output struct. This is then passed to the the following func which is called:&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Uses network message [[#TransferNext|TransferNext]].&lt;br /&gt;
** Calls a func.&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]].&lt;br /&gt;
* If the output from two funcs which load state match, calls a func.&lt;br /&gt;
* Cleanup, then returns.&lt;br /&gt;
&lt;br /&gt;
=== CompleteAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
This async task does the following (handling any errors as needed / calling any logging funcs as needed):&lt;br /&gt;
&lt;br /&gt;
* ...&lt;br /&gt;
* Calls a vfunc. When the ret is false:&lt;br /&gt;
** Throws an error if not [[#ConnectByServerIdAsync|connected]].&lt;br /&gt;
** If a state flag is not set, calls the same func as [[#TransferNextAsync|TransferNextAsync]] for generate_key_seed_package.&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization0Async|DebugSynchronizeStateInFinalization0Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateInFinalization1Async|DebugSynchronizeStateInFinalization1Async]].&lt;br /&gt;
** Calls the same func as [[#DebugSynchronizeStateFinalizedAsync|DebugSynchronizeStateFinalizedAsync]].&lt;br /&gt;
** Calls a func which handles disconnecting from the network, without using the network message. This also clears the connected state flag.&lt;br /&gt;
* Calls the same vfunc as above again, throwing an error if the ret is still false.&lt;br /&gt;
* Handles [[Sockets_services|sockets]] initialization.&lt;br /&gt;
* Calls a func.&lt;br /&gt;
* Enters a block which uses nifm.&lt;br /&gt;
* Calls a func which uses network request [[Network|transfer_events/%lld/finish_transfer]].&lt;br /&gt;
* Nifm usage ends here.&lt;br /&gt;
* Handles cleanup for [[Sockets_services|sockets]].&lt;br /&gt;
* When successful at this point it runs the following block:&lt;br /&gt;
** Calls a func. (fs related?)&lt;br /&gt;
** Calls a func.&lt;br /&gt;
** Calls a func, which logs a report with [[PSC_services|srepo]].&lt;br /&gt;
** Calls a vfunc.&lt;br /&gt;
** Calls a vfunc (with locking before/after).&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization0Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 3.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateInFinalization1Async ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls vfuncs and uses network message [[#SynchronizeState|SynchronizeState]] with value 4.&lt;br /&gt;
&lt;br /&gt;
=== DebugSynchronizeStateFinalizedAsync ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides various validation, the async task essentially just calls a func which calls a vfunc and uses network message [[#SynchronizeState|SynchronizeState]] with value 5.&lt;br /&gt;
&lt;br /&gt;
== IServer ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IServer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetServerProfile_3|GetServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 21 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 40 || &lt;br /&gt;
|-&lt;br /&gt;
| 50 || &lt;br /&gt;
|-&lt;br /&gt;
| 60 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 120 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 121 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 130 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== GetServerProfile ===&lt;br /&gt;
Unofficial name.&lt;br /&gt;
&lt;br /&gt;
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd230 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd510 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].&lt;br /&gt;
&lt;br /&gt;
== IClient ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IClient&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 111 || &lt;br /&gt;
|-&lt;br /&gt;
| 200 || &lt;br /&gt;
|-&lt;br /&gt;
| 210 || &lt;br /&gt;
|-&lt;br /&gt;
| 220 || &lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 240 || &lt;br /&gt;
|-&lt;br /&gt;
| 250 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 700 || &lt;br /&gt;
|-&lt;br /&gt;
| 710 || &lt;br /&gt;
|-&lt;br /&gt;
| 720 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUnknown ==&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 110 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== IUploader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IUploader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 101 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 340 || &lt;br /&gt;
|-&lt;br /&gt;
| 350 || &lt;br /&gt;
|-&lt;br /&gt;
| 360 || [22.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 611 || [21.0.0+]&lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd100 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd610 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].&lt;br /&gt;
&lt;br /&gt;
== IDownloader ==&lt;br /&gt;
This is &amp;quot;nn::migration::device::IDownloader&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [20.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 20 || &lt;br /&gt;
|-&lt;br /&gt;
| 30 || &lt;br /&gt;
|-&lt;br /&gt;
| 90 || &lt;br /&gt;
|-&lt;br /&gt;
| 100 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || &lt;br /&gt;
|-&lt;br /&gt;
| 310 || &lt;br /&gt;
|-&lt;br /&gt;
| 320 || &lt;br /&gt;
|-&lt;br /&gt;
| 330 || &lt;br /&gt;
|-&lt;br /&gt;
| 390 || [21.0.0+] &lt;br /&gt;
|-&lt;br /&gt;
| 400 || &lt;br /&gt;
|-&lt;br /&gt;
| 500 || &lt;br /&gt;
|-&lt;br /&gt;
| 610 || &lt;br /&gt;
|-&lt;br /&gt;
| 620 || &lt;br /&gt;
|-&lt;br /&gt;
| 900 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cmd500 ===&lt;br /&gt;
No input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].&lt;br /&gt;
&lt;br /&gt;
=== Cmd900 ===&lt;br /&gt;
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].&lt;br /&gt;
&lt;br /&gt;
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].&lt;br /&gt;
&lt;br /&gt;
= ServerProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
Any data here which is initialized is usually zeros?&lt;br /&gt;
&lt;br /&gt;
= ClientProfile =&lt;br /&gt;
This is a 0x100-byte struct.&lt;br /&gt;
&lt;br /&gt;
It&#039;s unknown whether user/savedata/device use the same struct (size is the same for these).&lt;br /&gt;
&lt;br /&gt;
This is usually all-zeros with savedata?&lt;br /&gt;
&lt;br /&gt;
= Protocol =&lt;br /&gt;
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.&lt;br /&gt;
&lt;br /&gt;
== AdvertiseData ==&lt;br /&gt;
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.&lt;br /&gt;
&lt;br /&gt;
The salt used with hashing below is the same regardless of the AdvertiseData.&lt;br /&gt;
&lt;br /&gt;
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.&lt;br /&gt;
&lt;br /&gt;
The Uuid used below is generated with &amp;lt;code&amp;gt;nn::util::GenerateUuid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== user ===&lt;br /&gt;
Used by nn::migration::user::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x58 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-byte salt&lt;br /&gt;
&lt;br /&gt;
=== savedata ===&lt;br /&gt;
Used by nn::migration::savedata::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x50 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
[20.0.0+]:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || AccountId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || ApplicationId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 0x4 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x128 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* AccountId&lt;br /&gt;
* ApplicationId&lt;br /&gt;
* ProductModel&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
=== device ===&lt;br /&gt;
Used by nn::migration::device::*.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Uuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || 0x4 || Count for the above array.&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || 0xC || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x160 || 0x20 || SHA256 hash&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hash is calculated by using SHA256-update with each field separately, followed by the salt:&lt;br /&gt;
* Uuid&lt;br /&gt;
* +0x10 size 0x40-bytes&lt;br /&gt;
* +0x50 size 0x4-bytes&lt;br /&gt;
* ServerProfile&lt;br /&gt;
* 0x100-bytes salt&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
Names are unofficial.&lt;br /&gt;
&lt;br /&gt;
Messages sent over the TCP socket start with the following header:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || MessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Data specific to each message follows.&lt;br /&gt;
&lt;br /&gt;
Messages are encrypted with AES-128-GCM (excluding the [[#KeyExchange|KeyExchange]] messages). The key is derived during the messsage-handling for KeyExchange. The 0xC-byte nonce is the 0x8-bytes derived by [[#KeyExchange|KeyExchange]], followed by a big-endian u32 counter (starting at 0x0). This counter is incremented each time a message is encrypted/decrypted. The GCM AAD is not used.&lt;br /&gt;
&lt;br /&gt;
The message size must match the expected fixed-size for the MessageId.&lt;br /&gt;
&lt;br /&gt;
Offsets in the below sections are relative to header+0 (for encrypted messages, this is the plaintext payload instead).&lt;br /&gt;
&lt;br /&gt;
Message requests are sent by the client to the server, then (unless noted otherwise) a response with the same MessageId is sent to the client from the server. The first sent request is [[#KeyExchange|KeyExchange]].&lt;br /&gt;
&lt;br /&gt;
For GCM encrypted messages, the encrypted data starts at +0x8, with the 0x10-byte AES-128-GCM MAC tag immediately afterwards. The first 0xC-bytes of plaintext is the nonce (which must match the expected one during decryption), followed by the payload (can be empty).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! MessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || [[#KeyExchange|KeyExchange]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || [[#Initialize|Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || [[#Challenge|Challenge]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x9 || [[#Initialize|Initialize2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#Leave|Leave]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || [[#Data|Data]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xFF || [[#Error|Error]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyExchange ===&lt;br /&gt;
Request:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (the first state u8 here is set to 0x1).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x10 || Ctr for [[SPL_services|ComputeCtr]] with the below data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x70 || Data encrypted with [[SPL_services|ComputeCtr]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x88 || 0x10 || CMAC over the above plaintext data ([[SPL_services|ComputeCmac]]).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext data has the following structure:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x28 || Passphrase for key derivation.&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x48 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The keyslot for spl is setup with: &amp;lt;code&amp;gt;GenerateAesKek(AccessKey, KeySource, Generation, Option=0); LoadAesKey(keyslot, AccessKey, KeySource);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! System Version || Generation&lt;br /&gt;
|-&lt;br /&gt;
| [4.0.0] || 0x0&lt;br /&gt;
|-&lt;br /&gt;
| [5.0.0-5.1.0] || 0x5&lt;br /&gt;
|-&lt;br /&gt;
| [6.0.0-6.2.0] || 0x6&lt;br /&gt;
|-&lt;br /&gt;
| [7.0.0-8.0.0] || 0x8&lt;br /&gt;
|-&lt;br /&gt;
| [9.0.0] || 0xA&lt;br /&gt;
|-&lt;br /&gt;
| [9.1.0-12.1.0] || 0xB&lt;br /&gt;
|-&lt;br /&gt;
| [13.0.0] || 0xD&lt;br /&gt;
|-&lt;br /&gt;
| [14.0.0] || 0xE&lt;br /&gt;
|-&lt;br /&gt;
| [15.0.0] || 0xF&lt;br /&gt;
|-&lt;br /&gt;
| [16.0.0] || 0x10&lt;br /&gt;
|-&lt;br /&gt;
| [17.0.0+] || 0x11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PBKDF2-HMAC-SHA256 is used with the first 0x28-bytes of the above plaintext as the passphrase, a 0x20-byte salt from fixed global data, iterations=1000, and i=1. The first 0x10-bytes of the output HMAC then used as the AES-128-GCM key for later messages. The following 0x8-bytes is used as the first 0x8-bytes of the nonce.&lt;br /&gt;
&lt;br /&gt;
=== Initialize ===&lt;br /&gt;
This request is sent after [[#KeyExchange|KeyExchange]]. The Initialize2 request is sent after [[#Challenge|Challenge]].&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x14 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The plaintext response payload is empty.&lt;br /&gt;
&lt;br /&gt;
When handling the response, the client sets a state flag. The Initialize2 message is the same as Initialize, except that state field isn&#039;t updated during response handling.&lt;br /&gt;
&lt;br /&gt;
=== Challenge ===&lt;br /&gt;
This is the first request sent after reconnecting to the server, when an existing connection was previously in use.&lt;br /&gt;
&lt;br /&gt;
Plaintext request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || Must match the random data previously sent by the client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x20 || Copied into state by the client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Leave ===&lt;br /&gt;
This is sent by the client prior to closing the socket and temporarily leaving the ldn network.&lt;br /&gt;
&lt;br /&gt;
The plaintext request/response payload are empty.&lt;br /&gt;
&lt;br /&gt;
=== Data ===&lt;br /&gt;
This is used by the client to send additional data following the message, likewise by the server in response.&lt;br /&gt;
&lt;br /&gt;
Plaintext payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Big-endian data chunksize.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Big-endian data size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The additional data is encrypted the same as if it were a message without the message-header, in chunks of up to {above chunksize}.&lt;br /&gt;
&lt;br /&gt;
Both fields must be non-zero, and the chunksize must match 0x100000.&lt;br /&gt;
&lt;br /&gt;
The first chunk starts with a header, with the rest being the actual payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || DataMessageId&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x7 || Data for the message if any, normally all-zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The DataMessageId in the response received by the client must match one of the expected values, which is usually only the value previously sent in the request. The received size must also match the expected value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DataMessageId (client/server) || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || [[#ClientProfileNetwork|ClientProfileNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || [[#AcceptDecline|AcceptDecline]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [[#PrepareTransferDisconnect|PrepareTransferDisconnect]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer|PrepareTransfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#TransferNext|TransferNext]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xF0 || [[#SynchronizeState|SynchronizeState]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x10 ====&lt;br /&gt;
This is sent by the client following the last vfunc call in [[#ConnectByServerIdAsync|ConnectByServerIdAsync]] where the bool ret is checked, with both true/false blocks. This follows [[#ClientProfileNetwork|ClientProfileNetwork]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x148 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the aforementioned vfunc returned true, the client only uses the response data for verifying that various fields match state. Otherwise when false the client uses this data.&lt;br /&gt;
&lt;br /&gt;
==== ClientProfileNetwork ====&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x100 || 0x4 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
==== 0x12 ====&lt;br /&gt;
This is sent by the client following DataMessageId 0x10, where the vfunc mentioned there returned false.&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0xC || &lt;br /&gt;
|-&lt;br /&gt;
| 0xC || Varies || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== AcceptDecline ====&lt;br /&gt;
This is sent by the client via [[#AcceptAsync|AcceptAsync]]/[[#DeclineAsync|DeclineAsync]]/[[#DeclineAsync2|DeclineAsync2]].&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[21.0.0+]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x10 || Input from [[#DeclineAsync2|DeclineAsync2]] (zeros with Accept).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
At +0x1 in the header prior to this request payload, after DataMessageId is now:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || 0 = Decline, 1 = Accept.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== PrepareTransferDisconnect ===&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] if a state flag is not set, prior to temporarily disconnecting from the network for using network request [[Network|transfer_events/%lld/save_datas/%lld/generate_key_seed_package]] (this usually not used since the state flag is already set?).&lt;br /&gt;
&lt;br /&gt;
The request only contains the 0x4-byte header. The u8 at header+0x1 (after DataMessageId) is set to &amp;lt;code&amp;gt;statefield==other_statefield&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
=== PrepareTransfer ===&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect|PrepareTransferDisconnect]] if using it was enabled).&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x20 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== TransferNext ===&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer|PrepareTransfer]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
Response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x8 || Zeros?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Rest of message || Transfer payload.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]] (see [[#Notes]]), which the client then imports.&lt;br /&gt;
&lt;br /&gt;
=== SynchronizeState ===&lt;br /&gt;
The client sends this via [[#ConnectByServerIdAsync|ConnectByServerIdAsync]], [[#CompleteAsync|CompleteAsync]], and DebugSynchronizeState*.&lt;br /&gt;
&lt;br /&gt;
Request payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x4 || See below.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Can be used by [[#ConnectByServerIdAsync|ConnectByServerIdAsync]].&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#DebugSynchronizeStateInFinalization0Async|InFinalization0]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#DebugSynchronizeStateInFinalization1Async|InFinalization1]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DebugSynchronizeStateFinalizedAsync|Finalized]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The response only contains the header.&lt;br /&gt;
&lt;br /&gt;
=== Error ===&lt;br /&gt;
This can be sent by the server to the client to signal that an error occurred.&lt;br /&gt;
&lt;br /&gt;
Plaintext response payload:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1 || ErrorType&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a state field is valid, it&#039;s used to load a Result from an array, otherwise the Result is determined from the above ErrorType.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
Savedata transfer (&amp;quot;nn::migration::savedata::IServer&amp;quot;/&amp;quot;nn::migration::savedata::IClient&amp;quot;) requires that accounts are linked to the same network-account. acc:su [[NS_services#IManagerForSystemService|IManagerForSystemService]] GetAccountId is used here. The server stores this Id into state, and also stores it in the [[LDN_services|ldn]] AdvertiseData. The client also verifies the Id in AdvertiseData against the Id from GetAccountId for the account(s) being used, during ScanServersAsync.&lt;br /&gt;
&lt;br /&gt;
[20.0.0+] [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision]] is now used instead of ISaveDataTransferManager. Besides [[Filesystem_services|SetKeySeedPackage]] being used now as needed, [[Filesystem_services|SetLocalKeySeedPackage]] is now used by the relevant functionality in [[#IClient_2|IClient]] TransferNextAsync.&lt;br /&gt;
&lt;br /&gt;
[S2] System Settings now has an additional menu once send-savedata is selected, for selecting whether to send to Nintendo Switch or Nintendo Switch 2. If Switch 2 is selected, and there&#039;s a S1 receiving, the S2 will display a message regarding wrong target system. The receiving system also displays an error. Note that savedata for S2-only applications is only listed with the dest-S2 option (S1-applications are also listed).&lt;br /&gt;
&lt;br /&gt;
[[Category:Services]]&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
</feed>