<?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-06-22T06:23:34Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=22.5.0&amp;diff=14789</id>
		<title>22.5.0</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=22.5.0&amp;diff=14789"/>
		<updated>2026-06-19T03:01:54Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* System Titles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Switch 22.5.0 system update was released on June 16, 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;
*   &lt;br /&gt;
*     The Nintendo eShop layout has been redesigned.&lt;br /&gt;
*     	&lt;br /&gt;
*           The Nintendo eShop color will now reflect the theme color if your theme in System Settings is set to “Basic Dark.”&lt;br /&gt;
*       &lt;br /&gt;
*     &lt;br /&gt;
*     User-Verification PIN can now be used to confirm when “Accessing Nintendo eShop” and “Using Saved Payment Methods.”&lt;br /&gt;
*     Added the ability to rewind 10 seconds/advance 10 seconds with the ZL and ZR Buttons when watching a full screen video in News or Nintendo eShop.&lt;br /&gt;
*     General system stability improvements to enhance the user&#039;s experience.&lt;br /&gt;
*    &lt;br /&gt;
&lt;br /&gt;
==System Titles==&lt;br /&gt;
* The following titles were updated:&lt;br /&gt;
** Sysmodules: usb, settings, bsdsocket, hid, wlan, account, ns, am, ssl, erpt, es, migration.&lt;br /&gt;
** SystemData (non-sysver): BrowserDll, Help, FirmwareDebugSettings, BootImagePackage, BootImagePackageSafe, BootImagePackageExFat, BootImagePackageExFatSafe, ClientCertData.&lt;br /&gt;
** Applets: qlaunch, auth, error, playerSelect, swkbd, LibAppletOff, myPage, splay, systemWeb, openWeb.&lt;br /&gt;
&lt;br /&gt;
[[NPDM]] changes (besides usual version-bump):&lt;br /&gt;
* LibAppletOff: Service access: removed bsd:a, bsdcfg, htcs:sys, nifm:u.&lt;br /&gt;
* systemWeb: Service access: removed htcs:sys.&lt;br /&gt;
* openWeb: Service access: removed htcs:sys.&lt;br /&gt;
&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* BrowserDll:&lt;br /&gt;
** &amp;quot;/browser/RootCaEtc.pem&amp;quot; updated&lt;br /&gt;
** &amp;quot;/buildinfo/buildinfo.dat&amp;quot; updated&lt;br /&gt;
** &amp;quot;/gfxShader/MediaPlayerDrawer.bnsh&amp;quot; updated&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/lyt/ImageViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/Lion.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/MediaViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/nro/netfront/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/cruiser.bfsar&amp;quot; updated&lt;br /&gt;
* Help: &amp;quot;/legallines.htdocs/index.html&amp;quot; updated&lt;br /&gt;
* [[System_Version_Title|SystemVersion]]: All files updated.&lt;br /&gt;
* [[System_Settings|FirmwareDebugSettings]]: All files updated.&lt;br /&gt;
* ClientCertData: All files updated.&lt;br /&gt;
* qlaunch applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/qlaunch_action.bksnd&amp;quot; updated&lt;br /&gt;
* auth applet: &amp;quot;/message/USen/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USfr/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USpt/common.msbt.szs&amp;quot; updated&lt;br /&gt;
* error applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* playerSelect applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* swkbd applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/swkbd_action.bksnd&amp;quot; updated&lt;br /&gt;
* [[Internet_Browser|LibAppletOff applet]]: All files updated.&lt;br /&gt;
* myPage applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/myPage_action.bksnd&amp;quot; updated&lt;br /&gt;
* systemWeb applet: All files updated.&lt;br /&gt;
* openWeb applet: All files updated.&lt;br /&gt;
* splay applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
&lt;br /&gt;
=== BootImagePackages ===&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* &amp;quot;/nx/package2&amp;quot; updated&lt;br /&gt;
&lt;br /&gt;
Only the KIPs were updated:&lt;br /&gt;
* FS&lt;br /&gt;
* Loader, only the anti-downgrade list.&lt;br /&gt;
* NCM was rebuilt (BuildId updated).&lt;br /&gt;
&lt;br /&gt;
=== [[USB_services|usb]] ===&lt;br /&gt;
Essentially only the [[USB_services#HidGamepad|HidGamepad]] json was updated.&lt;br /&gt;
&lt;br /&gt;
=== [[Settings_services|settings]] ===&lt;br /&gt;
Support for OSM was added for [[Settings_services#ProductModelName|ProductModelName]]/[[Settings_services#ProductModel|ProductModel]].&lt;br /&gt;
&lt;br /&gt;
=== [[Sockets_services|bsdsocket]] ===&lt;br /&gt;
Two entries for &amp;quot;AccountProfile&amp;quot; were added in .rodata (any other changes are minor?).&lt;br /&gt;
&lt;br /&gt;
=== [[WLAN_services|wlan]] ===&lt;br /&gt;
* Updated L_633d0, prev ver @ L_633d0.&lt;br /&gt;
** Besides minor other changes, calls L_fb610 (new func) to get a global flag. Later when that flag is set, a bounds check is now done.&lt;br /&gt;
* Updated L_fb880, prev ver @ L_fb840.&lt;br /&gt;
** Another strcmp call was added for handling an additional entry. Before returning, this now sets the flag used by L_fb610 to whether the input string matches &amp;quot;S5&amp;quot;.&lt;br /&gt;
* Updated L_fc9c0, prev ver @ L_fc930.&lt;br /&gt;
&lt;br /&gt;
=== [[Applet_Manager_services|am]] ===&lt;br /&gt;
A change introduced in [[22.0.0#am|22.0.0]] that broke the traditional homebrew launching method has been reverted.&lt;br /&gt;
&lt;br /&gt;
=== [[Migration_services|migration]] ===&lt;br /&gt;
Besides SDK-related changes, the only changes were:&lt;br /&gt;
&lt;br /&gt;
* L_188250 from prev ver was removed, an identical func located elsewhere is now called instead.&lt;br /&gt;
* Updated L_18a1c0, prev ver @ L_189a00.&lt;br /&gt;
** This is eventually called by the async task for nn::migration::device::IServer cmd100, etc.&lt;br /&gt;
* Updated L_18ae10, prev ver @ L_18a640.&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-06-16_01-01-38&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=22.5.0&amp;diff=14788</id>
		<title>22.5.0</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=22.5.0&amp;diff=14788"/>
		<updated>2026-06-17T22:10:24Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* System Titles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Switch 22.5.0 system update was released on June 16, 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;
*   &lt;br /&gt;
*     The Nintendo eShop layout has been redesigned.&lt;br /&gt;
*     	&lt;br /&gt;
*           The Nintendo eShop color will now reflect the theme color if your theme in System Settings is set to “Basic Dark.”&lt;br /&gt;
*       &lt;br /&gt;
*     &lt;br /&gt;
*     User-Verification PIN can now be used to confirm when “Accessing Nintendo eShop” and “Using Saved Payment Methods.”&lt;br /&gt;
*     Added the ability to rewind 10 seconds/advance 10 seconds with the ZL and ZR Buttons when watching a full screen video in News or Nintendo eShop.&lt;br /&gt;
*     General system stability improvements to enhance the user&#039;s experience.&lt;br /&gt;
*    &lt;br /&gt;
&lt;br /&gt;
==System Titles==&lt;br /&gt;
* The following titles were updated:&lt;br /&gt;
** Sysmodules: usb, settings, bsdsocket, hid, wlan, account, ns, am, ssl, erpt, es, migration.&lt;br /&gt;
** SystemData (non-sysver): BrowserDll, Help, FirmwareDebugSettings, BootImagePackage, BootImagePackageSafe, BootImagePackageExFat, BootImagePackageExFatSafe, ClientCertData.&lt;br /&gt;
** Applets: qlaunch, auth, error, playerSelect, swkbd, LibAppletOff, myPage, splay, systemWeb, openWeb.&lt;br /&gt;
&lt;br /&gt;
[[NPDM]] changes (besides usual version-bump):&lt;br /&gt;
* LibAppletOff: Service access: removed bsd:a, bsdcfg, htcs:sys, nifm:u.&lt;br /&gt;
* systemWeb: Service access: removed htcs:sys.&lt;br /&gt;
* openWeb: Service access: removed htcs:sys.&lt;br /&gt;
&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* BrowserDll:&lt;br /&gt;
** &amp;quot;/browser/RootCaEtc.pem&amp;quot; updated&lt;br /&gt;
** &amp;quot;/buildinfo/buildinfo.dat&amp;quot; updated&lt;br /&gt;
** &amp;quot;/gfxShader/MediaPlayerDrawer.bnsh&amp;quot; updated&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/lyt/ImageViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/Lion.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/MediaViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/nro/netfront/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/cruiser.bfsar&amp;quot; updated&lt;br /&gt;
* Help: &amp;quot;/legallines.htdocs/index.html&amp;quot; updated&lt;br /&gt;
* [[System_Version_Title|SystemVersion]]: All files updated.&lt;br /&gt;
* [[System_Settings|FirmwareDebugSettings]]: All files updated.&lt;br /&gt;
* ClientCertData: All files updated.&lt;br /&gt;
* qlaunch applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/qlaunch_action.bksnd&amp;quot; updated&lt;br /&gt;
* auth applet: &amp;quot;/message/USen/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USfr/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USpt/common.msbt.szs&amp;quot; updated&lt;br /&gt;
* error applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* playerSelect applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* swkbd applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/swkbd_action.bksnd&amp;quot; updated&lt;br /&gt;
* [[Internet_Browser|LibAppletOff applet]]: All files updated.&lt;br /&gt;
* myPage applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/myPage_action.bksnd&amp;quot; updated&lt;br /&gt;
* systemWeb applet: All files updated.&lt;br /&gt;
* openWeb applet: All files updated.&lt;br /&gt;
* splay applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
&lt;br /&gt;
=== BootImagePackages ===&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* &amp;quot;/nx/package2&amp;quot; updated&lt;br /&gt;
&lt;br /&gt;
Only the KIPs were updated:&lt;br /&gt;
* FS&lt;br /&gt;
* Loader, only the anti-downgrade list.&lt;br /&gt;
* NCM was rebuilt (BuildId updated).&lt;br /&gt;
&lt;br /&gt;
=== [[USB_services|usb]] ===&lt;br /&gt;
Essentially only the [[USB_services#HidGamepad|HidGamepad]] json was updated.&lt;br /&gt;
&lt;br /&gt;
=== [[Settings_services|settings]] ===&lt;br /&gt;
Support for OSM was added for [[Settings_services#ProductModelName|ProductModelName]]/[[Settings_services#ProductModel|ProductModel]].&lt;br /&gt;
&lt;br /&gt;
=== [[Sockets_services|bsdsocket]] ===&lt;br /&gt;
Two entries for &amp;quot;AccountProfile&amp;quot; were added in .rodata (any other changes are minor?).&lt;br /&gt;
&lt;br /&gt;
=== [[WLAN_services|wlan]] ===&lt;br /&gt;
* Updated L_633d0, prev ver @ L_633d0.&lt;br /&gt;
** Besides minor other changes, calls L_fb610 (new func) to get a global flag. Later when that flag is set, a bounds check is now done.&lt;br /&gt;
* Updated L_fb880, prev ver @ L_fb840.&lt;br /&gt;
** Another strcmp call was added for handling an additional entry. Before returning, this now sets the flag used by L_fb610 to whether the input string matches &amp;quot;S5&amp;quot;.&lt;br /&gt;
* Updated L_fc9c0, prev ver @ L_fc930.&lt;br /&gt;
&lt;br /&gt;
=== [[Applet_Manager_services|am]] ===&lt;br /&gt;
A change introduced in [[22.0.0#am|22.0.0]] that broke the traditional homebrew launching method has been reverted.&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-06-16_01-01-38&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=Switch_2:_Title_list&amp;diff=14787</id>
		<title>Switch 2: Title list</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Switch_2:_Title_list&amp;diff=14787"/>
		<updated>2026-06-16T22:53:39Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* System Data Archives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= System Modules =&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! ProgramId || Versions || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000006 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[USB_services|usb]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000008 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Boot2|boot2]] (debug)&amp;lt;br/&amp;gt; [[Boot2|boot2.SafeMode]] (safe)&amp;lt;br/&amp;gt;  [[Boot2|boot2.FromHost]] (develop)&amp;lt;br/&amp;gt; [[Boot2|boot2.prodBoot]] (retail)&amp;lt;br/&amp;gt;[[Boot2|boot2.manuBoot]] (factory)&amp;lt;br/&amp;gt;[[Boot2|boot2.Manu1st]] (factory) || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000009 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Settings_services|settings]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000000A || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Bus_services|Bus]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000000B || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.1|v1343321424]] (20.1.1.30032)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Bluetooth_Driver_services|bluetooth.autog]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000000C || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[BCAT_services|bcat]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000000E || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Friend_services|friends]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000000F || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Network_Interface_services|nifm]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000010 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[PTM_services|ptm]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000012 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Sockets_services|bsdsocket]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000013 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[HID_services|hid]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000014 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Audio_services|audio]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000015 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Log_services|LogManager]] (debug)&amp;lt;br/&amp;gt;[[Log_services|LogManager.Prod]] (retail) || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000016 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.5.0|v1347450282]] (20.5.0.30122)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[WLAN_services|wlan]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000018 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[LDN_services|ldn]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000019 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[NV_services|nvservices]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000001A || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[PCV_services|pcv]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000001B || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Capmtp_services|capmtp]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000001D || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[PCIe_services|pcie]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000001E || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.5.0|v1347450282]] (20.5.0.30122)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Account_services|account]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000001F || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[NS_Services|ns]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000020 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[NFC_services|nfc]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000021 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[PSC_services|psc]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000022 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Capture_services|capsrv]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000023 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[AM_services|am]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000024 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[SSL_services|ssl]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000025 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[NIM_services|nim]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000002B || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Error_Report_services|erpt]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000002E || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Parental_Control_services|pctl]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000002F || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[NPNS_services|npns]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000030 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Error_Upload_services|eupld]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000031 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.5.0|v1347450282]] (20.5.0.30122)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Glue_services|glue]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000032 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || eclct || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000033 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[ETicket_services|es]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000034 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.1.5|v1343583688]] (20.1.5.30152)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Fatal_services|fatal]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000035 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[GRC_services|grc]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000036 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[creport]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000037 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[RO_services|ro]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000039 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172) || [[Shared_Database_services|sdb]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000003A || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.1|v1343321424]] (20.1.1.30032)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Migration_services|migration]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000003C || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Jpegdec_services|jpegdec]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000003E || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[OLSC_services|olsc]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000042 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[PGL_services|pgl]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000045 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172) || [[OMM_services|omm]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000046 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Ethernet_services|eth]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000047 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000004A || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000004D || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000004F || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000050 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || ngc || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000052 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000062 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000063 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000065 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000070 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172) || [20.1.0+] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000071 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000072 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000080 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000081 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000083 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000084 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000088 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000089 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000008D || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= System Data Archives =&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! ProgramId || Versions || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000800 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[SSL_services#CertStore|CertStore]] || Same as NX.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000802 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || MiiModel || Same as NX.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000803 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257898]] (20.1.0.32042)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Internet_Browser#BrowserDll|BrowserDll]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000804 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257748]] (20.1.0.31892)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || Help || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000806 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || NgWord || Same as NX. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000807 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [[Hotspot_List|SsidList]] || Same as NX. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000808 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1342209022]] (20.0.0.31742)&amp;lt;br/&amp;gt; [[Switch 2: 21.0.0|v1409316656]] (21.0.0.30512)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || Dictionary || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000809 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.1|v1343321424]] (20.1.1.30032)&amp;lt;br/&amp;gt; [[Switch 2: 20.5.0|v1347450282]] (20.5.0.30122)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[System_Version_Title|SystemVersion]] || [20.1.1+] The digest file is no longer present.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000080A || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || AvatarImage || Now just contains &amp;quot;DatabaseInfo.byml.zs&amp;quot; and PNGs in directories &amp;quot;512x512&amp;quot;/&amp;quot;Ocean512x512&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000080C || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257808]] (20.1.0.31952) || Eula || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000080D || [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [21.0.0+] UrlBlackList || Same as NX.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000080E || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || TimeZoneBinary || Same as NX.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000810 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || FontNintendoExtension || Same as NX except &amp;quot;nintendo_ext2_003.bfttf&amp;quot; was removed.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000811 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || FontStandard || Same as NX.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000812 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || FontKorean || Same as NX.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000813 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || FontChineseTraditional || Same as NX.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000814 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || FontChineseSimple || Same as NX.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000816 || [[Switch 2: 19.0.0|v1275070438]] (19.0.0.2022)&amp;lt;br/&amp;gt; [[Switch 2: 20.1.1|v1343321424]] (20.1.1.30032)&amp;lt;br/&amp;gt; [[Switch 2: 20.1.5|v1343583688]] (20.1.5.30152)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 20.3.0|v1345353070]] (20.3.0.30062)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401921]] (20.4.0.30337)&amp;lt;br/&amp;gt; [[Switch 2: 20.5.0|v1347450282]] (20.5.0.30122)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || SystemUpdate || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000818 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Switch 2: System_Settings|FirmwareDebugSettings]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000819 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || BootImagePackage || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000081B || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] BootImagePackageExFat || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000081D || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || FatalMessage || Compared to NX, &amp;quot;/{lang}/GeneralMessage&amp;quot; were updated, and &amp;quot;zh-CN/&amp;quot; + &amp;quot;zh-TW/&amp;quot; were removed.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000081E || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.0.0|v1342209022]] (20.0.0.31742) || ControllerIcon || Now just contains &amp;quot;Footer/controllerIcon.bntx&amp;quot; and &amp;quot;Footer/info.dat&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000822 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172) || [[HID_services#Firmware_Update|ControllerFirmware]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000823 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || NgWord2 || Same as NX. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000826 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257748]] (20.1.0.31892)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 21.0.0|v1409316656]] (21.0.0.30512) || RebootlessSystemUpdateVersion || Version fields were reset to starting with value 1. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000827 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102))&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] ContentActionTable || Same as NX. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000828 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257938]] (20.1.0.32082)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 21.0.0|v1409316656]] (21.0.0.30512) || [[#Shared_Database_services#FunctionBlackList|FunctionBlackList]] || This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000832 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || CradleFirmware || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000834 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Additional [[Switch 2: System_Settings|system-settings]].&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000835 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257928]] (20.1.0.32072)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || ErrorMessageUtf8 || This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000836 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains data for the wifi/bluetooth controller, including firmware.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000837 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] || This is a SystemProgram, so this likely contains the [[Switch 2: Compatibility Mode|compat-modules]].&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000083A || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains &amp;quot;nintendo_udsg-r_std_004.bfttf&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000083B || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains &amp;quot;nintendo_udsg-db_std_004.bfttf&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000083C || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains &amp;quot;nintendo_udsg-r_ko_004.bfttf&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000083D || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains &amp;quot;nintendo_udsg-db_ko_004.bfttf&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000083E || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains &amp;quot;nintendo_udsg-r_zh-tw_004.bfttf&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000083F || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains &amp;quot;nintendo_udsg-db_zh-tw_004.bfttf&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000840 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains &amp;quot;nintendo_udsg-r_ext_zh-cn_004.bfttf&amp;quot; and &amp;quot;nintendo_udsg-r_org_zh-cn_004.bfttf&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000841 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains &amp;quot;nintendo_udsg-db_ext_zh-cn_004.bfttf&amp;quot; and &amp;quot;nintendo_udsg-db_org_zh-cn_004.bfttf&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000842 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Contains &amp;quot;nintendo_ext_004.bfttf&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000843 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] || This is a SystemProgram, so this likely contains the [[Switch 2: Compatibility Mode|compat-modules]].&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000844 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Contains data for face detection.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000846 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || [20.1.0+] Contains an empty &amp;quot;Dummy&amp;quot; ([19.0.0] contains 0x3C-byte files: &amp;quot;WrappedKey0Dev.bin&amp;quot;, &amp;quot;WrappedKey0End.bin&amp;quot;, &amp;quot;WrappedKey0EndQuest.bin&amp;quot;).&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000847 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.0.0|v1342209022]] (20.0.0.31742) || || Contains &amp;quot;MiiBody.dat&amp;quot; and shaders.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000848 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.5.0|v1347450282]] (20.5.0.30122)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] [[Switch 2: Compatibility Mode|ApplicationCompatibilityInfo]] || This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000849 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || This appears to be MiiModel updated for Ounce (similar filenames except with &amp;quot;NX&amp;quot; -&amp;gt; &amp;quot;Ounce&amp;quot;, etc).&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000084A || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Contains ja-JP voice data.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000084B || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Contains en-US voice data.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000084C || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Contains fr-FR voice data.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000084D || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Contains de-DE voice data.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000084E || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Only on FirmwareVariationId 0xC. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] value 0x10.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000084F || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Only on FirmwareVariationId 0xC. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] value 0x10.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000850 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Only on FirmwareVariationId 0xC. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] value 0x10.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000851 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Only on FirmwareVariationId 0xC. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] value 0x10.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000852 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Only on FirmwareVariationId 0xC. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] value 0x10.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000853 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Contains en-GB voice data.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000854 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Only on FirmwareVariationId 0xC. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] value 0x10.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000855 || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] || Contains es-MX voice data.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000858 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Same as NgWord2. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000859 || [[Switch 2: 20.1.0|v1343257748]] (20.1.0.31892)&amp;lt;br/&amp;gt; [[Switch 2: 20.5.0|v1347450282]] (20.5.0.30122)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] ClientCertData || Compared to NX, &amp;quot;meta.json&amp;quot; was filled in, and &amp;quot;eshop_p01_prod.p12&amp;quot; + &amp;quot;eshop_p01_urls.txt&amp;quot; were added (latter contains a single URL whitelist line).&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000085A || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002) || || Contains &amp;quot;ProductLogo.bin&amp;quot; and &amp;quot;ProductLogoMeta.bin&amp;quot;. This is the raw image data for the logo displayed during system-boot.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000085B || [[Switch 2: 20.1.0|v1343257898]] (20.1.0.32042)&amp;lt;br/&amp;gt; [[Switch 2: 20.5.0|v1347450282]] (20.5.0.30122)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] || Contains &amp;quot;/{lang}/gaiji.lex&amp;quot; and &amp;quot;/{lang}/userdict.csv&amp;quot;. [22.5.0+] This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000085C || [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [20.1.0+] GameCardConfigurationData || Contains &amp;quot;GameCardConfigurationData.bin&amp;quot;, which was updated compared to NX. This has [[NCM_services#ContentMetaAttributes|ContentMetaAttributes]] = Rebootless.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000085D || [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [21.0.0+] BrowserCoreDll || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000000860 || [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || [21.0.0+] CameraFirmware || Contains &amp;quot;NintendoSwitch2CameraFirmware.bin&amp;quot;, Squashfs image for the Linux camera firmware.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= System Applets =&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! ProgramId || Versions || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001000 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.1|v1343321424]] (20.1.1.30032)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || qlaunch (SystemAppletMenu) || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001001 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Auth_Applet|auth]] (LibraryAppletAuth) || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001003 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Controller_Applet|controller]] (LibraryAppletController) || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001005 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Error_Applet|error]] (LibraryAppletError) || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001007 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Profile Selector|playerSelect (LibraryAppletPlayerSelect)]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001008 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Software Keyboard|swkbd (LibraryAppletSwkbd)]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001009 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || miiEdit (LibraryAppletMiiEdit) || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000100C || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257928]] (20.1.0.32072)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || overlayDisp (OverlayApplet)  || This is also used for cmenu.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000100D || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[Album_Applet|photoViewer (LibraryAppletPhotoViewer)]] || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000100E || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257948]] (20.1.0.32092)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || set (LibraryAppletSet) || &lt;br /&gt;
|-&lt;br /&gt;
| 040000000000100F || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257898]] (20.1.0.32042)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001013 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.1.0|v1477473756]] (22.1.0.30172)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [[MyPage_Applet|myPage (LibraryAppletMyPage)]] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001015 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || maintenance (MaintenanceMenu) || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001041 || [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001042 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257898]] (20.1.0.32042)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || LibAppletShop (LibraryAppletShop)  || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001043 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257898]] (20.1.0.32042)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || OpenWeb || &lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001045 || [[Switch 2: 20.1.1|v1343321424]] (20.1.1.30032)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.1+] || Only on FirmwareVariationId 0xB.&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000001048 || [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 20.2.0|v1344304624]] (20.2.0.30192)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || [20.1.0+] splay || Only on FirmwareVariationId 0xB.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000104B || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257898]] (20.1.0.32042)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || || Only on FirmwareVariationId 0xB.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000104C || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 20.4.0|v1346401916]] (20.4.0.30332)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Only on FirmwareVariationId 0xB.&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000104D || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257908]] (20.1.0.32052)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572)&amp;lt;br/&amp;gt; [[Switch 2: 22.5.0|v1481668160]] (22.5.0.30272) || || Only on FirmwareVariationId 0xB.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Development System Applications =&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! ProgramId || Versions || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
| 0400000000002065 || || DevMenuApp ||&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000218F || || BluetoothHciRelayTool ||&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000219A || || WlanBtRelayTool ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Development System Modules =&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! ProgramId || Versions || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
| 040000000000B240 || [[Switch 2: 19.0.0|v1275070418]] (19.0.0.2002)&amp;lt;/br&amp;gt; [[Switch 2: 20.1.0|v1343257958]] (20.1.0.32102)&amp;lt;br/&amp;gt; [[Switch 2: 22.0.0|v1476425580]] (22.0.0.30572) || || Present on retail devices, likely (?) stubbed. Only on FirmwareVariationId 0xB.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= System Applications =&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! ProgramId || Versions || Description || Notes&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= User Applications =&lt;br /&gt;
Refer to the [[Switch 2: Title_list/Games|Games List]] for game and application programs.&lt;/div&gt;</summary>
		<author><name>Yellows8</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=22.5.0&amp;diff=14780</id>
		<title>22.5.0</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=22.5.0&amp;diff=14780"/>
		<updated>2026-06-16T21:22:09Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Switch 22.5.0 system update was released on June 16, 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;
*   &lt;br /&gt;
*     The Nintendo eShop layout has been redesigned.&lt;br /&gt;
*     	&lt;br /&gt;
*           The Nintendo eShop color will now reflect the theme color if your theme in System Settings is set to “Basic Dark.”&lt;br /&gt;
*       &lt;br /&gt;
*     &lt;br /&gt;
*     User-Verification PIN can now be used to confirm when “Accessing Nintendo eShop” and “Using Saved Payment Methods.”&lt;br /&gt;
*     Added the ability to rewind 10 seconds/advance 10 seconds with the ZL and ZR Buttons when watching a full screen video in News or Nintendo eShop.&lt;br /&gt;
*     General system stability improvements to enhance the user&#039;s experience.&lt;br /&gt;
*    &lt;br /&gt;
&lt;br /&gt;
==System Titles==&lt;br /&gt;
* The following titles were updated:&lt;br /&gt;
** Sysmodules: usb, settings, bsdsocket, hid, wlan, account, ns, am, ssl, erpt, es, migration.&lt;br /&gt;
** SystemData (non-sysver): BrowserDll, Help, FirmwareDebugSettings, BootImagePackage, BootImagePackageSafe, BootImagePackageExFat, BootImagePackageExFatSafe, ClientCertData.&lt;br /&gt;
** Applets: qlaunch, auth, error, playerSelect, swkbd, LibAppletOff, myPage, splay, systemWeb, openWeb.&lt;br /&gt;
&lt;br /&gt;
[[NPDM]] changes (besides usual version-bump):&lt;br /&gt;
* LibAppletOff: Service access: removed bsd:a, bsdcfg, htcs:sys, nifm:u.&lt;br /&gt;
* systemWeb: Service access: removed htcs:sys.&lt;br /&gt;
* openWeb: Service access: removed htcs:sys.&lt;br /&gt;
&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* BrowserDll:&lt;br /&gt;
** &amp;quot;/browser/RootCaEtc.pem&amp;quot; updated&lt;br /&gt;
** &amp;quot;/buildinfo/buildinfo.dat&amp;quot; updated&lt;br /&gt;
** &amp;quot;/gfxShader/MediaPlayerDrawer.bnsh&amp;quot; updated&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/lyt/ImageViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/Lion.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/MediaViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/nro/netfront/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/cruiser.bfsar&amp;quot; updated&lt;br /&gt;
* Help: &amp;quot;/legallines.htdocs/index.html&amp;quot; updated&lt;br /&gt;
* [[System_Version_Title|SystemVersion]]: All files updated.&lt;br /&gt;
* [[System_Settings|FirmwareDebugSettings]]: All files updated.&lt;br /&gt;
* ClientCertData: All files updated.&lt;br /&gt;
* qlaunch applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/qlaunch_action.bksnd&amp;quot; updated&lt;br /&gt;
* auth applet: &amp;quot;/message/USen/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USfr/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USpt/common.msbt.szs&amp;quot; updated&lt;br /&gt;
* error applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* playerSelect applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* swkbd applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/swkbd_action.bksnd&amp;quot; updated&lt;br /&gt;
* [[Internet_Browser|LibAppletOff applet]]: All files updated.&lt;br /&gt;
* myPage applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/myPage_action.bksnd&amp;quot; updated&lt;br /&gt;
* systemWeb applet: All files updated.&lt;br /&gt;
* openWeb applet: All files updated.&lt;br /&gt;
* splay applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
&lt;br /&gt;
=== BootImagePackages ===&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* &amp;quot;/nx/package2&amp;quot; updated&lt;br /&gt;
&lt;br /&gt;
Only the KIPs were updated:&lt;br /&gt;
* FS&lt;br /&gt;
* Loader, only the anti-downgrade list.&lt;br /&gt;
* NCM was rebuilt (BuildId updated).&lt;br /&gt;
&lt;br /&gt;
=== [[USB_services|usb]] ===&lt;br /&gt;
Essentially only the [[USB_services#HidGamepad|HidGamepad]] json was updated.&lt;br /&gt;
&lt;br /&gt;
=== [[Settings_services|settings]] ===&lt;br /&gt;
Support for OSM was added for [[Settings_services#ProductModelName|ProductModelName]]/[[Settings_services#ProductModel|ProductModel]].&lt;br /&gt;
&lt;br /&gt;
=== [[Sockets_services|bsdsocket]] ===&lt;br /&gt;
Two entries for &amp;quot;AccountProfile&amp;quot; were added in .rodata (any other changes are minor?).&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-06-16_01-01-38&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=USB_services&amp;diff=14779</id>
		<title>USB services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=USB_services&amp;diff=14779"/>
		<updated>2026-06-16T20:19:32Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* HidGamepad */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;USB provides services for interacting with the USB stack.&lt;br /&gt;
&lt;br /&gt;
= usb:ds =&lt;br /&gt;
[1.0.0-10.2.0] This is &amp;quot;nn::usb::ds::IDsService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[11.0.0+] This is &amp;quot;nn::usb::ds::IDsRootSession&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This service is used during [[Factory Setup|factory setup]] by [[Manu Services|manu]]. This is also used by [[Capmtp_services|capmtp]].&lt;br /&gt;
&lt;br /&gt;
This service session is used as an IPC [[IPC_Marshalling|domain]] by [[Manu Services|manu]].&lt;br /&gt;
&lt;br /&gt;
This service can be used by multiple processes at the same time, with separate interfaces. However, if one process does usbds shutdown, usbds will reset to defaults even if there&#039;s a process still using it.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#CreateDsService]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateDsService ==&lt;br /&gt;
No input. Returns an [[#IDsService]].&lt;br /&gt;
&lt;br /&gt;
== IDsService ==&lt;br /&gt;
This is &amp;quot;nn::usb::ds::IDsService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#Initialize]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [11.0.0+] [[#RegisterInterface]] ([1.0.0-10.2.0] [[#BindClientProcess]]))&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [11.0.0+] [[#GetStateChangeEvent]] ([1.0.0-10.2.0] [[#RegisterInterface]])&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [11.0.0+] [[#GetState]] ([1.0.0-10.2.0] [[#GetStateChangeEvent]])&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [11.0.0+] ClearDeviceData ([1.0.0-10.2.0] [[#GetState]])&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [11.0.0+] AddUsbStringDescriptor ([5.0.0-10.2.0] ClearDeviceData, [2.0.0-4.1.0] [[#SetVidPidBcd]])&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [11.0.0+] DeleteUsbStringDescriptor ([5.0.0-10.2.0] AddUsbStringDescriptor)&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [11.0.0+] SetUsbDeviceDescriptor ([5.0.0-10.2.0] DeleteUsbStringDescriptor)&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [11.0.0+] SetBinaryObjectStore ([5.0.0-10.2.0] SetUsbDeviceDescriptor)&lt;br /&gt;
|-&lt;br /&gt;
| 9 || [11.0.0+] EnableDevice ([5.0.0-10.2.0] SetBinaryObjectStore)&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [11.0.0+] DisableDevice ([5.0.0-10.2.0] EnableDevice)&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [11.0.0+] [[#GetSpeed]] ([5.0.0-10.2.0] DisableDevice)&lt;br /&gt;
|-&lt;br /&gt;
| 12 || [8.0.0-10.2.0] [[#GetSpeed]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Initialize ==&lt;br /&gt;
Takes an input u32 &#039;&#039;&#039;ComplexId&#039;&#039;&#039;. No output.&lt;br /&gt;
&lt;br /&gt;
[11.0.0+] Now takes an additional input Process handle.&lt;br /&gt;
&lt;br /&gt;
[[Manu_Services|Manu]] uses &#039;&#039;&#039;ComplexId&#039;&#039;&#039; 0x02.&lt;br /&gt;
&lt;br /&gt;
Binding more than once with the current session is not allowed. Once this command is used, the USB device will not be listed with &amp;lt;code&amp;gt;lsusb&amp;lt;/code&amp;gt; until [[#EnableInterface]] is used.&lt;br /&gt;
&lt;br /&gt;
Returns a not-found error when &#039;&#039;&#039;ComplexId&#039;&#039;&#039; isn&#039;t 0x02, for values 0x0-0x4 at least.&lt;br /&gt;
&lt;br /&gt;
== BindClientProcess ==&lt;br /&gt;
Takes an input Process handle. No output.&lt;br /&gt;
&lt;br /&gt;
== RegisterInterface ==&lt;br /&gt;
Takes two type-0x5 input buffers containing an [[#UsbInterfaceDescriptor]] and an [[#UsbStringDescriptor]], respectively. Returns an output u8 &#039;&#039;&#039;InterfaceNumber&#039;&#039;&#039; and an [[#IDsInterface]].&lt;br /&gt;
&lt;br /&gt;
[5.0.0+] This now only takes an input u8 and returns an [[#IDsInterface]].&lt;br /&gt;
&lt;br /&gt;
[[Manu_Services|Manu]] sends a 0x09-byte descriptor (e.g.: 0x09, 0x04, 0x04, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00) in the first buffer and a string (&amp;quot;usb&amp;quot;) in the second buffer.&lt;br /&gt;
&lt;br /&gt;
When the strlen output for the second buffer is &amp;gt;=0x40, size 0x40 is used instead for copying the string. This is the interface name, it&#039;s not sent over USB.&lt;br /&gt;
&lt;br /&gt;
Returns an error when [[#Initialize]] wasn&#039;t used.&lt;br /&gt;
&lt;br /&gt;
Up to 4 interfaces can be used and [[#EnableInterface|enabled]].&lt;br /&gt;
&lt;br /&gt;
== GetStateChangeEvent ==&lt;br /&gt;
No input. Returns an output Event handle.&lt;br /&gt;
&lt;br /&gt;
Signalled when Switch&amp;lt;-&amp;gt;host USB comms change between started/stopped. USB cable connected/disconnected while at least 1 interface was enabled, or interface enabled/disabled while the USB cable was connected which then caused USB-comms state to change.&lt;br /&gt;
&lt;br /&gt;
== GetState ==&lt;br /&gt;
No input. Returns an output [[#UsbState]].&lt;br /&gt;
&lt;br /&gt;
Returns an error when [[#Initialize]] wasn&#039;t used.&lt;br /&gt;
&lt;br /&gt;
== SetVidPidBcd ==&lt;br /&gt;
Takes a type-0x5 input buffer containing an [[#UsbVidPidBcd]]. No output.&lt;br /&gt;
&lt;br /&gt;
== GetSpeed ==&lt;br /&gt;
No input. Returns an output [[#UsbDeviceSpeed]].&lt;br /&gt;
&lt;br /&gt;
== IDsInterface ==&lt;br /&gt;
This is &amp;quot;nn::usb::ds::IDsInterface&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#RegisterEndpoint]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetSetupEvent]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetSetupPacket]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [11.0.0+] [[#CtrlInAsync]] ([1.0.0-10.2.0] [[#Enable]])&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [11.0.0+] [[#CtrlOutAsync]] ([1.0.0-10.2.0] [[#Disable]])&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [11.0.0+] [[#GetCtrlInCompletionEvent]] ([1.0.0-10.2.0] [[#CtrlInAsync]])&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [11.0.0+] [[#GetCtrlInUrbReport]] ([1.0.0-10.2.0] [[#CtrlOutAsync]])&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [11.0.0+] [[#GetCtrlOutCompletionEvent]] ([1.0.0-10.2.0] [[#GetCtrlInCompletionEvent]])&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [11.0.0+] [[#GetCtrlOutUrbReport]] ([1.0.0-10.2.0] [[#GetCtrlInUrbReport]])&lt;br /&gt;
|-&lt;br /&gt;
| 9 || [11.0.0+] [[#CtrlStall]] ([1.0.0-10.2.0] [[#GetCtrlOutCompletionEvent]])&lt;br /&gt;
|-&lt;br /&gt;
| 10 || [11.0.0+] [[#AppendConfigurationData]] ([1.0.0-10.2.0] [[#GetCtrlOutUrbReport]])&lt;br /&gt;
|-&lt;br /&gt;
| 11 || [13.0.0+] [[#SetGuid]] ([1.0.0-10.2.0] [[#CtrlStall]])&lt;br /&gt;
|-&lt;br /&gt;
| 12 || [15.0.0+] [[#RegisterTransferMemory]] ([5.0.0-10.2.0] [[#AppendConfigurationData]])&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== RegisterEndpoint ===&lt;br /&gt;
Takes a type-0x5 input buffer containing an [[#UsbEndpointDescriptor]]. Returns an output u8 &#039;&#039;&#039;EndpointNumber&#039;&#039;&#039; and an [[#IDsEndpoint]].&lt;br /&gt;
&lt;br /&gt;
[5.0.0+] This now only takes an input u8 and returns an [[#IDsEndpoint]].&lt;br /&gt;
&lt;br /&gt;
[[Manu_Services|Manu]] uses this twice for getting two endpoint sessions, with the following 0x7-byte buffer data:&lt;br /&gt;
* First endpoint: 0x07, 0x05, 0x80, 0x02, 0x00, 0x02, 0x00&lt;br /&gt;
** bLength=0x7&lt;br /&gt;
** bDescriptorType=LIBUSB_DT_ENDPOINT&lt;br /&gt;
** bEndpointAddress=LIBUSB_ENDPOINT_IN&lt;br /&gt;
** bmAttributes=LIBUSB_TRANSFER_TYPE_BULK&lt;br /&gt;
** wMaxPacketSize=0x200&lt;br /&gt;
** bInterval=0&lt;br /&gt;
* Second endpoint: Same as above except byte2 is 0x00(bEndpointAddress=LIBUSB_ENDPOINT_OUT).&lt;br /&gt;
&lt;br /&gt;
The buffer size must be &amp;gt;=0x7. Only the first 0x7-bytes from the buffer are used.&lt;br /&gt;
* Byte0(bLength) must match 0x7.&lt;br /&gt;
* Byte1(bDescriptorType) must match 0x5.&lt;br /&gt;
* Byte2(bEndpointAddress) is only compared with 0x80 to determine whether to use an input or output endpoint, the actual endpoint-number is allocated automatically by checking state. Hence, all input endpoints must use bEndpointAddress==0x80. Up to endpoint-number 0xF can be allocated for each endpoint-direction, for a total of 16 endpoints including control, and 15 for non-control endpoints([[#IDsEndpoint]] sessions for each direction). This matches the Tegra maximum.&lt;br /&gt;
&lt;br /&gt;
From the Tegra datasheet: &amp;quot;The maximum packet size supported on any endpoint is 1024 bytes in high-speed mode, for both device and host modes.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Throws an error if the interface is [[#EnableInterface|enabled]].&lt;br /&gt;
&lt;br /&gt;
=== GetSetupEvent ===&lt;br /&gt;
No input. Returns an output Event handle.&lt;br /&gt;
&lt;br /&gt;
Unknown what triggers signalling, not signalled during interface-enable / device&amp;lt;&amp;gt;host USB-comms init.&lt;br /&gt;
&lt;br /&gt;
=== GetSetupPacket ===&lt;br /&gt;
Takes a type-0x6 output buffer. No output.&lt;br /&gt;
&lt;br /&gt;
Memcpys data to outbuf with outsize, uses size 0x8 if outsize is too large.&lt;br /&gt;
&lt;br /&gt;
Throws an error if the interface is not [[#EnableInterface|enabled]].&lt;br /&gt;
&lt;br /&gt;
=== Enable ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
Enables the current interface.&lt;br /&gt;
&lt;br /&gt;
Only one interface can be enabled at a time per bInterfaceNumber. When bInterfaceNumber is auto-allocate(0x4) for [[#RegisterEndpoint]] this isn&#039;t an issue since the final bInterfaceNumber will be unique.&lt;br /&gt;
&lt;br /&gt;
Once enabled, the device/interface can then actually be used over USB.&lt;br /&gt;
&lt;br /&gt;
=== Disable ===&lt;br /&gt;
No input/output. &lt;br /&gt;
&lt;br /&gt;
Disables the current interface.&lt;br /&gt;
&lt;br /&gt;
=== CtrlInAsync ===&lt;br /&gt;
Same as [[#PostBufferAsync]], except this uses control input endpoint 0x80.&lt;br /&gt;
&lt;br /&gt;
Throws an error if the interface is not [[#EnableInterface|enabled]].&lt;br /&gt;
&lt;br /&gt;
=== CtrlOutAsync ===&lt;br /&gt;
Same as [[#PostBufferAsync]], except this uses control output endpoint 0x00.&lt;br /&gt;
&lt;br /&gt;
Throws an error if the interface is not [[#EnableInterface|enabled]].&lt;br /&gt;
&lt;br /&gt;
=== GetCtrlInCompletionEvent ===&lt;br /&gt;
Same as [[#GetCompletionEvent]], except this uses control input endpoint 0x80.&lt;br /&gt;
&lt;br /&gt;
=== GetCtrlInUrbReport ===&lt;br /&gt;
Same as [[#GetUrbReport]], except this uses control input endpoint 0x80.&lt;br /&gt;
&lt;br /&gt;
=== GetCtrlOutCompletionEvent ===&lt;br /&gt;
Same as [[#GetCompletionEvent]], except this uses control output endpoint 0x00.&lt;br /&gt;
&lt;br /&gt;
=== GetCtrlOutUrbReport ===&lt;br /&gt;
Same as [[#GetUrbReport]], except this uses control output endpoint 0x00.&lt;br /&gt;
&lt;br /&gt;
=== CtrlStall ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
Calls a function with both control endpoints (0x80 and 0x00) with the same function. From strings: &amp;quot;m_pProtocol-&amp;gt;Stall(0x80)&amp;quot; &amp;quot;m_pProtocol-&amp;gt;Stall(0x00)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Throws an error if the interface is not [[#EnableInterface|enabled]].&lt;br /&gt;
&lt;br /&gt;
=== AppendConfigurationData ===&lt;br /&gt;
Takes an input u32 &#039;&#039;&#039;InterfaceNumber&#039;&#039;&#039;, an input [[#UsbDeviceSpeed]] and a type-0x5 input buffer. No output.&lt;br /&gt;
&lt;br /&gt;
[5.0.0+] This now only takes an input [[#UsbDeviceSpeed]] and a type-0x5 input buffer.&lt;br /&gt;
&lt;br /&gt;
=== SetGuid ===&lt;br /&gt;
Takes a type-0x5 input buffer. No output.&lt;br /&gt;
&lt;br /&gt;
=== RegisterTransferMemory ===&lt;br /&gt;
Takes an input u64 and an input handle. No output.&lt;br /&gt;
&lt;br /&gt;
Stubbed, just returns an error.&lt;br /&gt;
&lt;br /&gt;
=== IDsEndpoint ===&lt;br /&gt;
This is &amp;quot;nn::usb::ds::IDsEndpoint&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#PostBufferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#Cancel]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetCompletionEvent]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#GetUrbReport]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#Stall]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#SetZlt]]&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [7.0.0+] [[#IsStalled]]&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [7.0.0+] [[#GetStallClearedEvent]]&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [11.0.0-14.1.2]&lt;br /&gt;
|-&lt;br /&gt;
| 9 || [11.0.0-14.1.2]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== PostBufferAsync ====&lt;br /&gt;
Takes an input u32 &#039;&#039;&#039;Size&#039;&#039;&#039; and an input u64 &#039;&#039;&#039;Buffer&#039;&#039;&#039;. Returns an output u32 &#039;&#039;&#039;UrbId&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The output urbId can then be used while parsing the output of [[#GetUrbReport]], after waiting for the CompletionEvent to be signalled.&lt;br /&gt;
&lt;br /&gt;
The buffer address must be 0x1000-byte aligned. The input size doesn&#039;t matter. It helps to use svcSetMemoryAttribute to turn off caching on the buffer.&lt;br /&gt;
&lt;br /&gt;
Used for data-transfer with input/output endpoints.&lt;br /&gt;
&lt;br /&gt;
The user-process must flush dcache for the buffer before using this command.&lt;br /&gt;
&lt;br /&gt;
When sending data where size is larger than wMaxPacketSize, it will automatically send multiple USB packets where last packet size = {remaining size}. Every {wMaxPacketSize}-bytes is a different packet. This only occurs in some cases. When &#039;&#039;&#039;size&#039;&#039;&#039; is ~0x1000000(exact size unknown), Switch-side silently hangs, while host-side will timeout(no traffic on USB bus indicating failure).&lt;br /&gt;
&lt;br /&gt;
For receiving data, if size is less than {actual received USB packet size} the rest of the packet will be discarded. Later PostBufferAsync cmd(s) will only return data from new packets, not the remainder of the earlier packet(s).&lt;br /&gt;
&lt;br /&gt;
==== Cancel ====&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
==== GetCompletionEvent ====&lt;br /&gt;
No input. Returns an output Event handle.&lt;br /&gt;
&lt;br /&gt;
==== GetUrbReport ====&lt;br /&gt;
No input. Returns an output [[#UrbReport]].&lt;br /&gt;
&lt;br /&gt;
Seems to be eventually loaded from state, since this doesn&#039;t trigger any USB bus activity. All-zero before PostBufferAsync was used at least once.&lt;br /&gt;
&lt;br /&gt;
==== Stall ====&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
Calls the same function used by [[#CtrlStall]], except this uses the endpoint associated with the current session.&lt;br /&gt;
&lt;br /&gt;
Stops in-progress data-transfer done by [[#PostBufferAsync]].&lt;br /&gt;
&lt;br /&gt;
==== SetZlt ====&lt;br /&gt;
Takes an input bool. No output.&lt;br /&gt;
&lt;br /&gt;
==== IsStalled ====&lt;br /&gt;
No input. Returns an output bool.&lt;br /&gt;
&lt;br /&gt;
==== GetStallClearedEvent ====&lt;br /&gt;
No input. Returns an output Event handle.&lt;br /&gt;
&lt;br /&gt;
==== Cmd8 ====&lt;br /&gt;
Takes an input u64 and an input handle. No output.&lt;br /&gt;
&lt;br /&gt;
Stubbed, just returns an error.&lt;br /&gt;
&lt;br /&gt;
==== Cmd9 ====&lt;br /&gt;
Takes an input u32 &#039;&#039;&#039;Size&#039;&#039;&#039; and an input u64 &#039;&#039;&#039;Offset&#039;&#039;&#039;. Returns an u32 &#039;&#039;&#039;UrbId&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Stubbed, just returns an error.&lt;br /&gt;
&lt;br /&gt;
= usb:hs, usb:hs:a =&lt;br /&gt;
This is &amp;quot;nn::usb::hs::IClientRootSession&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[7.0.0+] usb:hs:a opens an nn::usb::hs::IClientRootSession, but sets an &amp;quot;isSystemClient&amp;quot; field in the object (and in interfaces/eps opened by the session) to false.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [2.0.0+] [[#BindClientProcess_2|#BindClientProcess]] ([1.0.0] [[#QueryAllInterfaces]])&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#QueryAllInterfaces]] ([1.0.0] [[#QueryAvailableInterfaces]])&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#QueryAvailableInterfaces]] ([1.0.0] [[#QueryAcquiredInterfaces]])&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#QueryAcquiredInterfaces]] ([1.0.0] [[#CreateInterfaceAvailableEvent]])&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#CreateInterfaceAvailableEvent]] ([1.0.0] [[#DestroyInterfaceAvailableEvent]])&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#DestroyInterfaceAvailableEvent]] ([1.0.0] [[#GetInterfaceStateChangeEvent]])&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [[#GetInterfaceStateChangeEvent]] ([1.0.0] [[#AcquireUsbIf]])&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [[#AcquireUsbIf]] ([1.0.0] [[#GetDescriptorString]])&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [6.0.0+] SetTestMode ([1.0.0] [[#ResetDevice]])&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
General USB devices usage, used by [[HID_services|hid]], [[Sockets_services|bsdsockets]], and [5.1.0+] [[Audio_services|audio]].&lt;br /&gt;
&lt;br /&gt;
Get-service-handle will fail if the current process is already using usb:ds, however it&#039;s successful if it&#039;s done separately from the process using usb:ds.&lt;br /&gt;
&lt;br /&gt;
== BindClientProcess ==&lt;br /&gt;
Takes 1 copy-handle for the current process (0xFFFF8001).&lt;br /&gt;
&lt;br /&gt;
== QueryAllInterfaces ==&lt;br /&gt;
Takes an [[#DeviceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries.&lt;br /&gt;
&lt;br /&gt;
The output buffer contains an array of [[#InterfaceQueryOutput]]. This returns the same interfaces as [[#QueryAvailableInterfaces]], followed by the interfaces also returned by [[#QueryAcquiredInterfaces]]. Except for the ID field in [[#InterfaceQueryOutput]], which is set to -1.&lt;br /&gt;
&lt;br /&gt;
== QueryAvailableInterfaces ==&lt;br /&gt;
Takes an [[#DeviceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries.&lt;br /&gt;
&lt;br /&gt;
The output buffer contains an array of [[#InterfaceQueryOutput]]. This only returns interfaces which are not acquired by any process.&lt;br /&gt;
&lt;br /&gt;
== QueryAcquiredInterfaces ==&lt;br /&gt;
Takes a type-0x6 output buffer and returns an output s32 total_entries.&lt;br /&gt;
&lt;br /&gt;
The output buffer contains an array of [[#InterfaceQueryOutput]], for each interface which was acquired with [[#AcquireUsbIf]].&lt;br /&gt;
&lt;br /&gt;
== CreateInterfaceAvailableEvent ==&lt;br /&gt;
Takes an input u8 and an [[#DeviceFilter]], and returns an output handle. The input value must be 0..2. This is used as an index in a table.&lt;br /&gt;
&lt;br /&gt;
The struct is located at +2 from the u8 in IPC rawdata.&lt;br /&gt;
&lt;br /&gt;
When signaled, this indicates that the user-process should use [[#QueryAvailableInterfaces]] and [[#AcquireUsbIf]] with the output interfaces (and the rest of interface setup).&lt;br /&gt;
&lt;br /&gt;
== DestroyInterfaceAvailableEvent ==&lt;br /&gt;
Takes an input u8, no output. The input value must be 0..2.&lt;br /&gt;
&lt;br /&gt;
Clears state associated with the input index. This is the same state setup by [[#CreateInterfaceAvailableEvent]].&lt;br /&gt;
&lt;br /&gt;
== GetInterfaceStateChangeEvent ==&lt;br /&gt;
No input, returns an output event handle with autoclear disabled.&lt;br /&gt;
&lt;br /&gt;
When signaled, this indicates that the user-process should use [[#QueryAcquiredInterfaces]] and cleanup state for interfaces which were already initialized and don&#039;t have any matching ID in [[#InterfaceProfile]] +0x0. When total_entries is less than 1, this indicates that cleanup should be done for all currently open interfaces.&lt;br /&gt;
&lt;br /&gt;
== AcquireUsbIf ==&lt;br /&gt;
Takes an input u32 and a type-0x6 output buffer, returns an [[#IClientIfSession]]. On [3.0.0+] this takes an additional type-0x6 output buffer, before the original buffer. On [3.0.0+] the first buffer is 0x70-bytes, while the second one is 0x1B8. The user-process has the second buffer address immediately after the first one, which allows getting a complete [[#InterfaceProfile]].&lt;br /&gt;
&lt;br /&gt;
The input u32 is from the u32 at entry+0 from the associated [[#QueryAvailableInterfaces]] output entry. User-processes use size 0x1B8 for the first output buffer. The first output buffer contains an [[#InterfaceProfile]].&lt;br /&gt;
&lt;br /&gt;
This returns an error if the interface was already acquired by another process.&lt;br /&gt;
&lt;br /&gt;
== GetDescriptorString ==&lt;br /&gt;
Takes a type-0x6 output buffer, an input u8, an input u8 bool, and an u32. Returns an output u32.&lt;br /&gt;
&lt;br /&gt;
The u32 is located at +4 from the first u8 in the IPC rawdata.&lt;br /&gt;
&lt;br /&gt;
Gets a string from a string descriptor.&lt;br /&gt;
&lt;br /&gt;
The UTF-16 string from descriptor+2 is copied to descriptor/outbuf +0, where each character is transferred using u8 not u16.&lt;br /&gt;
&lt;br /&gt;
Official sw doesn&#039;t use this, [[#SubmitControlInRequest]] is used instead.&lt;br /&gt;
&lt;br /&gt;
== ResetDevice ==&lt;br /&gt;
Takes an input u32, no output. Stubbed, just returns 0.&lt;br /&gt;
&lt;br /&gt;
== IClientIfSession ==&lt;br /&gt;
This is &amp;quot;nn::usb::hs::IClientIfSession&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name &lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetStateChangeEvent]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#SetInterface]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetInterface]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#GetAlternateInterface]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#GetCurrentFrame]] ([1.0.0] [[#CtrlXferAsync]])&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [2.0.0+] [[#CtrlXferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [[#GetCtrlXferCompletionEvent]] ([1.0.0] [[#SubmitControlInRequest]])&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [[#GetCtrlXferReport]] ([1.0.0] [[#SubmitControlOutRequest]])&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [[#ResetDevice]]&lt;br /&gt;
|-&lt;br /&gt;
| 9 || [[#OpenUsbEp]] ([1.0.0] [[#GetCurrentFrame]])&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Official sw uses autoclear=false for the above events.&lt;br /&gt;
&lt;br /&gt;
Immediately after opening the session, official sw uses cmd0 and cmd6.&lt;br /&gt;
&lt;br /&gt;
=== GetStateChangeEvent ===&lt;br /&gt;
No input, returns an output handle.&lt;br /&gt;
&lt;br /&gt;
=== SetInterface ===&lt;br /&gt;
Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains an [[#InterfaceProfile]].&lt;br /&gt;
&lt;br /&gt;
=== GetInterface ===&lt;br /&gt;
Takes a type-0x6 output buffer, no output. The output buffer contains an [[#InterfaceProfile]].&lt;br /&gt;
&lt;br /&gt;
=== GetAlternateInterface ===&lt;br /&gt;
Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains an [[#InterfaceProfile]]. The buffer size must match 0x1B8.&lt;br /&gt;
&lt;br /&gt;
=== GetCurrentFrame ===&lt;br /&gt;
No input, returns an output u32.&lt;br /&gt;
&lt;br /&gt;
On 1.0.0 this stubbed: this returns 0 with output u32 = hard-coded 0.&lt;br /&gt;
&lt;br /&gt;
=== CtrlXferAsync ===&lt;br /&gt;
Takes 2 input u8s (&#039;&#039;&#039;bmRequestType&#039;&#039;&#039; and &#039;&#039;&#039;bRequest&#039;&#039;&#039;), 3 input u16s (&#039;&#039;&#039;wValue&#039;&#039;&#039;, &#039;&#039;&#039;wIndex&#039;&#039;&#039;, and &#039;&#039;&#039;wLength&#039;&#039;&#039;), and an input u64 &#039;&#039;&#039;buffer&#039;&#039;&#039;, no output.&lt;br /&gt;
&lt;br /&gt;
=== GetCtrlXferCompletionEvent ===&lt;br /&gt;
No input, returns an output handle. Signaled when [[#CtrlXferAsync]] finishes.&lt;br /&gt;
&lt;br /&gt;
=== GetCtrlXferReport ===&lt;br /&gt;
Takes a type-0x6 output buffer, no output. The output buffer contains a [[#XferReport]].&lt;br /&gt;
&lt;br /&gt;
=== SubmitControlInRequest ===&lt;br /&gt;
Takes a type-0x6 output buffer, 2 input u8s (&#039;&#039;&#039;bRequest&#039;&#039;&#039; and &#039;&#039;&#039;bRequestType&#039;&#039;&#039;), 3 input u16s (&#039;&#039;&#039;wValue&#039;&#039;&#039;, &#039;&#039;&#039;wIndex&#039;&#039;&#039;, and &#039;&#039;&#039;wLength&#039;&#039;&#039;), and an input u32 &#039;&#039;&#039;timeoutInMs&#039;&#039;&#039;. Returns an output u32 for the actual transferred size.&lt;br /&gt;
&lt;br /&gt;
Official user-processes uses a buffer where the buffer address/size is page-aligned, where &#039;&#039;&#039;wLength&#039;&#039;&#039; is the original size before alignment. The user-process also flushes dcache for this buffer using &#039;&#039;&#039;wLength&#039;&#039;&#039;, before/after using this command. Official sw passes value 0 for &#039;&#039;&#039;timeoutInMs&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== SubmitControlOutRequest ===&lt;br /&gt;
Takes a type-0x5 input buffer, 2 input u8s (&#039;&#039;&#039;bRequest&#039;&#039;&#039; and &#039;&#039;&#039;bRequestType&#039;&#039;&#039;), 3 input u16s (&#039;&#039;&#039;wValue&#039;&#039;&#039;, &#039;&#039;&#039;wIndex&#039;&#039;&#039;, and &#039;&#039;&#039;wLength&#039;&#039;&#039;), and an input u32 &#039;&#039;&#039;timeoutInMs&#039;&#039;&#039;. Returns an output u32 for the actual transferred size.&lt;br /&gt;
&lt;br /&gt;
Official user-processes uses a buffer where the buffer address/size is page-aligned, where &#039;&#039;&#039;wLength&#039;&#039;&#039; is the original size before alignment. The user-process also flushes dcache for this buffer using &#039;&#039;&#039;wLength&#039;&#039;&#039;, before using this command. Official sw passes value 0 for &#039;&#039;&#039;timeoutInMs&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== ResetDevice ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
Resets the device: has the same affect as unplugging the device and plugging it back in.&lt;br /&gt;
&lt;br /&gt;
=== OpenUsbEp ===&lt;br /&gt;
Takes an input u16 and 4 input u32s, returns a 0x7-byte output struct and an [[#IClientEpSession]].&lt;br /&gt;
&lt;br /&gt;
The u16 is &#039;&#039;&#039;maxUrbCount&#039;&#039;&#039;. The u32s are: &#039;&#039;&#039;epType&#039;&#039;&#039;, &#039;&#039;&#039;epNumber&#039;&#039;&#039;, &#039;&#039;&#039;epDirection&#039;&#039;&#039;, and &#039;&#039;&#039;maxXferSize&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The user-process loads the input params from the endpoint descriptor. HID-sysmodule sets &#039;&#039;&#039;maxXferSize&#039;&#039;&#039; to wMaxPacketSize from the endpoint descriptor. However, other sysmodules pass hard-coded values for &#039;&#039;&#039;maxXferSize&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
HID-sysmodule passes hard-coded value 0x1 for &#039;&#039;&#039;maxUrbCount&#039;&#039;&#039;, for bsd-sysmodule this is 0x2. For audio-sysmodule, this is 0x3 or 0x6.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;epType&#039;&#039;&#039; is &amp;lt;code&amp;gt;libusb_transfer_type+1&amp;lt;/code&amp;gt;. &#039;&#039;&#039;epNumber&#039;&#039;&#039; is &amp;lt;code&amp;gt;bEndpointAddress &amp;amp; LIBUSB_ENDPOINT_ADDRESS_MASK&amp;lt;/code&amp;gt;. &#039;&#039;&#039;epDirection&#039;&#039;&#039; is 0x1 for LIBUSB_ENDPOINT_OUT, and 0x2 for LIBUSB_ENDPOINT_IN.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;epType&#039;&#039;&#039;, &#039;&#039;&#039;epNumber&#039;&#039;&#039;, and &#039;&#039;&#039;epDirection&#039;&#039;&#039; must all match USB-sysmodule state for the associated endpoint. &#039;&#039;&#039;maxUrbCount&#039;&#039;&#039; must be &amp;lt;0x11. &#039;&#039;&#039;maxXferSize&#039;&#039;&#039; must be &amp;lt;=0xFF0000. &amp;lt;code&amp;gt;maxUrbCount*maxXferSize&amp;lt;/code&amp;gt; must be non-zero.&lt;br /&gt;
&lt;br /&gt;
=== IClientEpSession ===&lt;br /&gt;
This is &amp;quot;nn::usb::hs::IClientEpSession&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#ReOpen]] ([1.0.0] [[#SubmitOutRequest]])&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#Close]] ([1.0.0] [[#SubmitInRequest]])&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetCompletionEvent_2|GetCompletionEvent]] ([1.0.0] Reset)&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#PopulateRing]] ([1.0.0] [[#Close]])&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [2.0.0+] [[#PostBufferAsync_2|#PostBufferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [2.0.0+] [[#GetXferReport]]&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [2.0.0+] [[#BatchBufferAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [4.0.0+] [[#CreateSmmuSpace]]&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [4.0.0+] [[#ShareReportRing]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Official sw uses autoclear=false for the above event.&lt;br /&gt;
&lt;br /&gt;
Immediately after opening the endpoint session, official sw uses [[#Populate]] and cmd2.&lt;br /&gt;
&lt;br /&gt;
==== SubmitOutRequest ====&lt;br /&gt;
Takes an type-0x5 input buffer, an u32 &#039;&#039;&#039;size&#039;&#039;&#039;, and an u32 &#039;&#039;&#039;unk&#039;&#039;&#039;. Returns an output u32 for the actual transferred size.&lt;br /&gt;
&lt;br /&gt;
Official user-processes uses a buffer where the buffer address/size is page-aligned, where &#039;&#039;&#039;size&#039;&#039;&#039; is the original size before alignment. The user-process also flushes dcache for this buffer using &#039;&#039;&#039;size&#039;&#039;&#039;, before using this command. Official sw passes value 0 for &#039;&#039;&#039;unk&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== SubmitInRequest ====&lt;br /&gt;
Takes an type-0x6 output buffer, an u32 &#039;&#039;&#039;size&#039;&#039;&#039;, and an u32 &#039;&#039;&#039;unk&#039;&#039;&#039;. Returns an output u32 for the actual transferred size.&lt;br /&gt;
&lt;br /&gt;
Official user-processes uses a buffer where the buffer address/size is page-aligned, where &#039;&#039;&#039;size&#039;&#039;&#039; is the original size before alignment. The user-process also flushes dcache for this buffer using &#039;&#039;&#039;size&#039;&#039;&#039;, before/after using this command. Official sw passes value 0 for &#039;&#039;&#039;unk&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== ReOpen ====&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
This is similar to [[#OpenUsbEp]] with the params being loaded from state instead.&lt;br /&gt;
&lt;br /&gt;
This is for re-opening after [[#Close]] was used.&lt;br /&gt;
&lt;br /&gt;
==== Close ====&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
Used by official sw prior to closing the endpoint session. The func for this is also called automatically by the sysmodule during the IClientEpSession dtor.&lt;br /&gt;
&lt;br /&gt;
==== GetCompletionEvent ====&lt;br /&gt;
No input, returns an output handle. Signaled when [[#PostBufferAsync_2|#PostBufferAsync]] finishes. ([1.0.0] [[#Open]])&lt;br /&gt;
&lt;br /&gt;
==== PopulateRing ====&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
Used after opening the endpoint session (see above).&lt;br /&gt;
&lt;br /&gt;
==== PostBufferAsync ====&lt;br /&gt;
Takes an input u32 &#039;&#039;&#039;size&#039;&#039;&#039;, an input u64 &#039;&#039;&#039;buffer&#039;&#039;&#039;, and an input u64 &#039;&#039;&#039;Id&#039;&#039;&#039;, returns an output u32 &#039;&#039;&#039;xferId&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Starts a data transfer with a single urb.&lt;br /&gt;
&lt;br /&gt;
The official sw func which uses this cmd and handles waiting on the Event passes value 0 for the &#039;&#039;&#039;Id&#039;&#039;&#039;. The async version which exposes this cmd directly uses &#039;&#039;&#039;Id&#039;&#039;&#039; from user input - the user funcs pass a value starting at 0 then increment it each time (for sending multiple requests at once, with 0 for the first request in this set of requests). Note that &#039;&#039;&#039;Id&#039;&#039;&#039; can be arbitrary, the sysmodule doesn&#039;t require a certain range for this.&lt;br /&gt;
&lt;br /&gt;
On newer sysvers the state fields setup by [[#CreateSmmuSpace]] are compared with &#039;&#039;&#039;buffer&#039;&#039;&#039;. If it&#039;s within bounds of the SmmuSpace (which won&#039;t be the case when [[#CreateSmmuSpace]] wasn&#039;t used), it will then verify that buffer+buffer_size is within bounds throwing an error otherwise. Note that a buffer from [[#CreateSmmuSpace]] can&#039;t be reused by another endpoint with PostBufferAsync.&lt;br /&gt;
&lt;br /&gt;
==== GetXferReport ====&lt;br /&gt;
Takes an input u32 and a type-0x6 ([3.0.0+] type-0x22) output buffer, returns an output u32 &#039;&#039;&#039;count&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The input u32 specifies the total number of entries to read, this must fit within the specified buffer size. The output u32 is the total actual output entries.&lt;br /&gt;
&lt;br /&gt;
The buffer contains an array of [[#XferReport]].&lt;br /&gt;
&lt;br /&gt;
On newer sysvers this runs code which is the same as the user-process code handling the tmem from [[#ShareReportRing]]. This cmd can handle getting reports from that tmem as well, however normally user-processes would just access the tmem [[#ShareReportRing|directly]].&lt;br /&gt;
&lt;br /&gt;
==== BatchBufferAsync ====&lt;br /&gt;
Takes 3 input u32s (&#039;&#039;&#039;urbCount&#039;&#039;&#039;, &#039;&#039;&#039;unk1&#039;&#039;&#039;, and &#039;&#039;&#039;unk2&#039;&#039;&#039;), an input u64 &#039;&#039;&#039;buffer&#039;&#039;&#039; and u64 &#039;&#039;&#039;Id&#039;&#039;&#039;, and a type-0x5 ([3.0.0+] type-0x21) input buffer, returns an output u32 &#039;&#039;&#039;xferId&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;&#039;Id&#039;&#039;&#039; is the same as [[#PostBufferAsync_2|#PostBufferAsync]].&lt;br /&gt;
&lt;br /&gt;
This uses the same func internally as [[#PostBufferAsync_2|#PostBufferAsync]] except multiple urbs are specified by the user: the input buffer contains an array of u32s for the size of each urb, where &#039;&#039;&#039;urbCount&#039;&#039;&#039; is the total number of entries in this array. With [[#PostBufferAsync_2|#PostBufferAsync]] the last 2 params passed to the internal func are hard-coded to 0, while with this command it&#039;s &#039;&#039;&#039;unk1&#039;&#039;&#039; and &#039;&#039;&#039;unk2&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== CreateSmmuSpace ====&lt;br /&gt;
Takes an input u32 &#039;&#039;&#039;size&#039;&#039;&#039; and an u64 &#039;&#039;&#039;buffer&#039;&#039;&#039;, no output.&lt;br /&gt;
&lt;br /&gt;
This validates that both input params are page-aligned. Official user-processes also validate this.&lt;br /&gt;
&lt;br /&gt;
This maps the specified buffer as devicemem and stores the fields for this in object state. If this was already used with this IClientEpSession object, an error is thrown.&lt;br /&gt;
&lt;br /&gt;
==== ShareReportRing ====&lt;br /&gt;
Takes an input u32 &#039;&#039;&#039;size&#039;&#039;&#039; and an input TransferMemory handle, no output.&lt;br /&gt;
&lt;br /&gt;
Official user-processes create the TransferMemory with permissions=RW. This validates that the input size is page-aligned, and this is also validated against data from state. Official user-processes also do this same validation.&lt;br /&gt;
&lt;br /&gt;
When this was used, official user-processes read data from this TransferMemory buffer instead of using [[#GetXferReport]].&lt;br /&gt;
&lt;br /&gt;
This maps a TransferMemory buffer which is used for the [[#XferReport]] Ring, replacing the heap Ring buffer which was setup during [[#PopulateRing]].&lt;br /&gt;
&lt;br /&gt;
Structure of the tmem:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || Write index&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || Read index&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x18*count || Array of [[#XferReport]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
write_index!=read_index indicates that report data is available. The index fields are updated with: &amp;lt;code&amp;gt;index = index+1 % count;&amp;lt;/code&amp;gt; write_index is updated by sysmodule, read_index is updated by the user-process. If the index field being used is &amp;gt;=count, this will Abort.&lt;br /&gt;
&lt;br /&gt;
= usb:pd =&lt;br /&gt;
This is &amp;quot;nn::usb::pd::detail::IPdManager&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#OpenSession]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Only system-titles with access to this are [[PTM_services|ptm]] and [[AM_services|am]].&lt;br /&gt;
&lt;br /&gt;
== OpenSession ==&lt;br /&gt;
No input. Returns an [[#IPdSession]].&lt;br /&gt;
&lt;br /&gt;
== IPdSession ==&lt;br /&gt;
This is &amp;quot;nn::usb::pd::detail::IPdSession&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || BindNoticeEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || UnbindNoticeEvent&lt;br /&gt;
|-&lt;br /&gt;
| 2 || GetStatus&lt;br /&gt;
|-&lt;br /&gt;
| 3 || GetNotice&lt;br /&gt;
|-&lt;br /&gt;
| 4 || EnablePowerRequestNotice&lt;br /&gt;
|-&lt;br /&gt;
| 5 || DisablePowerRequestNotice&lt;br /&gt;
|-&lt;br /&gt;
| 6 || ReplyPowerRequest&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= usb:pd:c =&lt;br /&gt;
This is &amp;quot;nn::usb::pd::detail::IPdCradleManager&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#OpenCradleSession]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
USB-sysmodule symbols for this refer to &amp;quot;Cradle&amp;quot;, which is the [[Dock]].&lt;br /&gt;
&lt;br /&gt;
== OpenCradleSession ==&lt;br /&gt;
No input. Returns an [[#IPdCradleSession]].&lt;br /&gt;
&lt;br /&gt;
== IPdCradleSession ==&lt;br /&gt;
This is &amp;quot;nn::usb::pd::detail::IPdCradleSession&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#SetCradleVdo]] &lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetCradleVdo]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#ResetCradleUsbHub]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [2.0.0+] [[#GetHostPdcFirmwareType]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [2.0.0+] [[#GetHostPdcFirmwareRevision]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [2.0.0+] [[#GetHostPdcManufactureId]]&lt;br /&gt;
|-&lt;br /&gt;
| 6 || [2.0.0+] [[#GetHostPdcDeviceId]]&lt;br /&gt;
|-&lt;br /&gt;
| 7 || [3.0.0+] [[#EnableCradleRecovery]]&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [3.0.0+] [[#DisableCradleRecovery]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SetCradleVdo ===&lt;br /&gt;
Takes an input u32 &#039;&#039;&#039;Value&#039;&#039;&#039; and a [[#CradleVdmCommand]]. No output.&lt;br /&gt;
&lt;br /&gt;
[[#CradleVdmCommand]] is translated to the actual [[#VdmCommand]] to send.&lt;br /&gt;
&lt;br /&gt;
=== GetCradleVdo ===&lt;br /&gt;
Takes an input [[#CradleVdmCommand]]. Returns an u32 &#039;&#039;&#039;Value&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[#CradleVdmCommand]] is translated to the actual [[#VdmCommand]] to send.&lt;br /&gt;
&lt;br /&gt;
=== ResetCradleUsbHub ===&lt;br /&gt;
No input/output.&lt;br /&gt;
&lt;br /&gt;
Sends [[#VdmCommand|VdmCommands]] 32 and 30.&lt;br /&gt;
&lt;br /&gt;
=== GetHostPdcFirmwareType ===&lt;br /&gt;
No input. Returns an output u16.&lt;br /&gt;
&lt;br /&gt;
=== GetHostPdcFirmwareRevision ===&lt;br /&gt;
No input. Returns an output u16.&lt;br /&gt;
&lt;br /&gt;
=== GetHostPdcManufactureId ===&lt;br /&gt;
No input. Returns an output u16.&lt;br /&gt;
&lt;br /&gt;
=== GetHostPdcDeviceId ===&lt;br /&gt;
No input. Returns an output u16.&lt;br /&gt;
&lt;br /&gt;
=== EnableCradleRecovery ===&lt;br /&gt;
No input. Returns an output u8.&lt;br /&gt;
&lt;br /&gt;
=== DisableCradleRecovery ===&lt;br /&gt;
No input. Returns an output u8.&lt;br /&gt;
&lt;br /&gt;
= usb:pd:m =&lt;br /&gt;
This is &amp;quot;nn::usb::pd::detail::IPdManufactureManager&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] This service was merged into [[#usb:pd:c|usb:pd:c]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#OpenManufactureSession]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== OpenManufactureSession ==&lt;br /&gt;
No input. Returns an [[#IPdManufactureSession]].&lt;br /&gt;
&lt;br /&gt;
== IPdManufactureSession ==&lt;br /&gt;
This is &amp;quot;nn::usb::pd::detail::IPdManufactureSession&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetHostPdcFirmwareType]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetHostPdcFirmwareRevision]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetHostPdcManufactureId]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#GetHostPdcDeviceId]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= usb:pm =&lt;br /&gt;
This is &amp;quot;nn::usb::pm::IPmService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[8.0.0+] This is &amp;quot;nn::usb::pm::IPmMainService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || [[#GetPowerEvent|GetPowerEvent]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#GetPowerState|GetPowerState]]&lt;br /&gt;
|-&lt;br /&gt;
| 2 || [[#GetDataEvent|GetDataEvent]]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [[#GetDataRole|GetDataRole]]&lt;br /&gt;
|-&lt;br /&gt;
| 4 || [[#SetDiagData|SetDiagData]]&lt;br /&gt;
|-&lt;br /&gt;
| 5 || [[#GetDiagData|GetDiagData]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
USB Port Manager, only system-title using this is [[PTM_services|ptm]].&lt;br /&gt;
&lt;br /&gt;
== GetPowerEvent ==&lt;br /&gt;
No input. Returns an output Event handle.&lt;br /&gt;
&lt;br /&gt;
== GetPowerState ==&lt;br /&gt;
Takes a type-0x6 output buffer containing an [[#UsbPowerState]]. No output.&lt;br /&gt;
&lt;br /&gt;
== GetDataEvent ==&lt;br /&gt;
No input. Returns an output Event handle.&lt;br /&gt;
&lt;br /&gt;
== GetDataRole ==&lt;br /&gt;
No input. Returns an output [[#UsbDataRole]].&lt;br /&gt;
&lt;br /&gt;
== SetDiagData ==&lt;br /&gt;
Takes two input u32s. No output.&lt;br /&gt;
&lt;br /&gt;
[8.0.0+] Stubbed, just returns 0.&lt;br /&gt;
&lt;br /&gt;
== GetDiagData ==&lt;br /&gt;
Takes an input u32. Returns an output u32.&lt;br /&gt;
&lt;br /&gt;
[8.0.0+] Stubbed, just returns 0.&lt;br /&gt;
&lt;br /&gt;
= usb:qdb =&lt;br /&gt;
This is &amp;quot;nn::usb::qdb::IQdbManager&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 || [[#ImportQuirkDevices]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || [[#HasQuirk]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ImportQuirkDevices ==&lt;br /&gt;
No input/output, takes a type-0x5 input buffer.&lt;br /&gt;
&lt;br /&gt;
This loads data for [[#HidGamepad]] with the input .json.&lt;br /&gt;
&lt;br /&gt;
== HasQuirk ==&lt;br /&gt;
Takes 6-bytes of input (u16s &#039;&#039;&#039;vid&#039;&#039;&#039;, &#039;&#039;&#039;pid&#039;&#039;&#039;, &#039;&#039;&#039;bcdDevice&#039;&#039;&#039;) and a type-0x5 input buffer, returns an output u8 bool indicating success.&lt;br /&gt;
&lt;br /&gt;
Locates an entry in the [[#HidGamepad]] state with the input u16s, and checks for a &#039;&#039;&#039;quirks&#039;&#039;&#039; array entry where &#039;&#039;&#039;name&#039;&#039;&#039; matches the input buffer string. Returns 1 when found, 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
= usb:obsv =&lt;br /&gt;
This is &amp;quot;nn::usb::pm::IPmObserverService&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This was added with [8.0.0+].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Cmd || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || GetTopologyChangeEvent&lt;br /&gt;
|-&lt;br /&gt;
| 1 || GetFlattenedTopology&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UsbInterfaceDescriptor =&lt;br /&gt;
This is &amp;quot;nn::usb::UsbInterfaceDescriptor&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || bLength&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || bDescriptorType&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x1 || bInterfaceNumber&lt;br /&gt;
|-&lt;br /&gt;
| 0x3 || 0x1 || bAlternateSetting&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x1 || bNumEndpoints&lt;br /&gt;
|-&lt;br /&gt;
| 0x5 || 0x1 || bInterfaceClass&lt;br /&gt;
|-&lt;br /&gt;
| 0x6 || 0x1 || bInterfaceSubClass&lt;br /&gt;
|-&lt;br /&gt;
| 0x7 || 0x1 || bInterfaceProtocol&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x1 || iInterface&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UsbStringDescriptor =&lt;br /&gt;
This is &amp;quot;nn::usb::UsbStringDescriptor&amp;quot;. This is a string.&lt;br /&gt;
&lt;br /&gt;
= UsbEndpointDescriptor =&lt;br /&gt;
This is &amp;quot;nn::usb::UsbEndpointDescriptor&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || bLength&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || 0x1 || bDescriptorType&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x1 || bEndpointAddress&lt;br /&gt;
|-&lt;br /&gt;
| 0x3 || 0x1 || bmAttributes&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || wMaxPacketSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x6 || 0x1 || bInterval&lt;br /&gt;
|-&lt;br /&gt;
| 0x7 || 0x1 || bRefresh&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x1 || bSynchAddress&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UsbState =&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Detached || Device is not attached to USB.&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Attached || Device is attached, but is not powered.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Powered || Device is attached and powered, but has not been reset.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Default || Device is attached, powered, and has been reset, but does not have an address.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Address || Device is attached, powered, has been reset, has an address, but is not configured.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Configured || Device is attached, powered, has been reset, has an address, configured, and may be used.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Suspended || Device is attached and powered, but has not seen bus activity for 3ms. Device is suspended and cannot be used.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UsbVidPidBcd =&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || Vid (idVendor)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Pid (idProduct)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || bcdDevice&lt;br /&gt;
|-&lt;br /&gt;
| 0x6 || 0x20 || Manufacturer (ASCII string padded to 0x20 bytes)&lt;br /&gt;
|-&lt;br /&gt;
| 0x26 || 0x20 || Product (ASCII string padded to 0x20 bytes)&lt;br /&gt;
|-&lt;br /&gt;
| 0x46 || 0x20 || SerialNumber (ASCII string padded to 0x20 bytes)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UrbReport =&lt;br /&gt;
{| class=&amp;quot;wikitable&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 * 8 || Array of [[#UrbReportEntry]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80 || 0x4 || ReportEntryCount&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UrbReportEntry =&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || Id&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || RequestedSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || TransferredSize&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || Status (converted to error-codes: 0x3 = success, 0x4 = 0x828c, 0x5 = 0x748c; all other values are invalid)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UsbDeviceSpeed =&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || None&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Low&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Full&lt;br /&gt;
|-&lt;br /&gt;
| 3 || High&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Super&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= InterfaceQueryOutput =&lt;br /&gt;
This is &amp;quot;nn::usb::InterfaceQueryOutput&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset || Size || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0 || 0x1B8 || [[#InterfaceProfile|InterfaceProfile]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1B8 || 0x40 || &amp;quot;HsDevice-/L&amp;lt;unk0&amp;gt;/P&amp;lt;portnum&amp;gt;/A&amp;lt;unk1&amp;gt;&amp;quot; string (this is &amp;quot;FsDevice...&amp;quot; for the Dock USB 3.0 bus).&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F8 || 0x4 || busID&lt;br /&gt;
|-&lt;br /&gt;
| 0x1FC || 0x4 || deviceID&lt;br /&gt;
|-&lt;br /&gt;
| 0x200 || 0x12+0x9(0x1B) || usb_device_descriptor, then usb_config_descriptor immediately afterwards.&lt;br /&gt;
|-&lt;br /&gt;
| 0x21B || 0x5 || Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x220 || 0x8 || Unknown u64 timestamp for when the device was inserted?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The INPUT/OUTPUT endpoint descriptors (usb_endpoint_descriptors/usb_ss_endpoint_companion_descriptors) were swapped with [8.0.0+] (above layout has the pre-8.0.0 layout), however the sysmodule code which writes this output struct was basically unchanged.&lt;br /&gt;
&lt;br /&gt;
= InterfaceProfile =&lt;br /&gt;
This is &amp;quot;nn::usb::InterfaceProfile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || ID value passed to other cmds. This is -1 with [[#QueryAllInterfaces]] output, hence this field is unused with that cmd.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || deviceID&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x9 || usb_interface_descriptor&lt;br /&gt;
|-&lt;br /&gt;
| 0x15 || 0x7 || Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 0x69 || OUTPUT usb_endpoint_descriptors, 15 max.&lt;br /&gt;
|-&lt;br /&gt;
| 0x85 || 0x7 || Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x8C || 0x69 || INPUT usb_endpoint_descriptors, 15 max.&lt;br /&gt;
|-&lt;br /&gt;
| 0xF5 || 0x6 || Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0xFB || 0x5A || OUTPUT usb_ss_endpoint_companion_descriptors(?), 15 max.&lt;br /&gt;
|-&lt;br /&gt;
| 0x155 || 0x6 || Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x15B || 0x5A || INPUT usb_ss_endpoint_companion_descriptors(?), 15 max.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1B5 || 0x3 || Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= DeviceFilter =&lt;br /&gt;
This is &amp;quot;nn::usb::DeviceFilter&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || Flags&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 ||idVendor&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || idProduct&lt;br /&gt;
|-&lt;br /&gt;
| 0x6 || 0x2 || bcdDevice_Min&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x2 || bcdDevice_Max&lt;br /&gt;
|-&lt;br /&gt;
| 0xA || 0x1 || bDeviceClass&lt;br /&gt;
|-&lt;br /&gt;
| 0xB || 0x1 || bDeviceSubClass&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x1 || bDeviceProtocol&lt;br /&gt;
|-&lt;br /&gt;
| 0xD || 0x1 || bInterfaceClass&lt;br /&gt;
|-&lt;br /&gt;
| 0xE || 0x1 || bInterfaceSubClass&lt;br /&gt;
|-&lt;br /&gt;
| 0xF || 0x1 || bInterfaceProtocol&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This is used to filter [[#InterfaceQueryOutput]], the query commands will only return the interface when these checks pass. This is also used for events with [[#CreateInterfaceAvailableEvent]]. When a bit in Flags is set, the associated descriptor field and the field in this struct are compared, on mismatch the interface will be filtered out. Passing Flags=0 is equivalent to disabling filtering since none of these checks will run.&lt;br /&gt;
&lt;br /&gt;
[7.0.0+]: The filter struct has to be unique, it can&#039;t match any existing filter structs used by [[#CreateInterfaceAvailableEvent]] (including other processes). Hence, Flags has to be non-zero. When initialized with usb:hs:a and VID and/or PID filtering is enabled, the VID/PID will be checked [[#HidGamepad]], with an error being throw if a matching device is found with quirk &amp;quot;ApplicationBlacklist&amp;quot; ([[#usb:qdb|usb:qdb]] cmd1 is used internally for this with bcdDevice=0).&lt;br /&gt;
&lt;br /&gt;
Flags bits 0..6 use usb_device_descriptor, while 7..9 use usb_interface_descriptor. Support for bits 2..6 and the associated fields was added with [6.0.0+].&lt;br /&gt;
&lt;br /&gt;
Flags bits:&lt;br /&gt;
* 0: idVendor&lt;br /&gt;
* 1: idProduct&lt;br /&gt;
* 2: bcdDevice (Descriptor value must be &amp;gt;= struct bcdDevice_Min)&lt;br /&gt;
* 3: bcdDevice (Descriptor value must be &amp;lt;= struct bcdDevice_Max)&lt;br /&gt;
* 4: bDeviceClass&lt;br /&gt;
* 5: bDeviceSubClass&lt;br /&gt;
* 6: bDeviceProtocol&lt;br /&gt;
* 7: bInterfaceClass&lt;br /&gt;
* 8: bInterfaceSubClass&lt;br /&gt;
* 9: bInterfaceProtocol&lt;br /&gt;
&lt;br /&gt;
HID-sysmodule uses the following for the input struct: &amp;lt;code&amp;gt;80 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= XferReport =&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || xferId (Only set for [[#GetXferReport]])&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || Result&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || requestedSize&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || transferredSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x8 || [[#PostBufferAsync_2|Id]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This is a 0x18-byte struct.&lt;br /&gt;
&lt;br /&gt;
Official sw only uses the Result/size fields.&lt;br /&gt;
&lt;br /&gt;
= CradleVdmCommand =&lt;br /&gt;
This is &amp;quot;nn::usb::pd::CradleVdmCommand&amp;quot;.&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 || 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;
| 4 || &lt;br /&gt;
|-&lt;br /&gt;
| 5 || &lt;br /&gt;
|-&lt;br /&gt;
| 6 || &lt;br /&gt;
|-&lt;br /&gt;
| 7 || &lt;br /&gt;
|-&lt;br /&gt;
| 8 || &lt;br /&gt;
|-&lt;br /&gt;
| 9 || &lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= VdmCommand =&lt;br /&gt;
This is &amp;quot;nn::usb::pd::driver::detail::VdmCommand&amp;quot;.&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 || [[#CradleVdmCommand|CradleVdmCommand]] || [[#VdmCommandType|VdmCommandType]] || VdmCommandLength || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || - || -1 || 0 || None&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 0 || 0 || 3 || LedControlRequest&lt;br /&gt;
|-&lt;br /&gt;
| 2 || - || 1 || 3 || LedControlReply&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 10 || 0 || 3 || DeviceTypeRequest&lt;br /&gt;
|-&lt;br /&gt;
| 4 || - || 1 || 3 || DeviceTypeReply&lt;br /&gt;
|-&lt;br /&gt;
| 5 || - || -1 || 0 || UsbPowerErrorNotice&lt;br /&gt;
|-&lt;br /&gt;
| 6 || 1 || 0 || 2 || Dp2HdmiFwVerRequest&lt;br /&gt;
|-&lt;br /&gt;
| 7 || - || 1 || 3 || Dp2HdmiFwVerReply&lt;br /&gt;
|-&lt;br /&gt;
| 8 || - || -1 || 0 || Dp2HdmiFwUpdateRequest&lt;br /&gt;
|-&lt;br /&gt;
| 9 || - || -1 || 0 || Dp2HdmiFwUpdateReply&lt;br /&gt;
|-&lt;br /&gt;
| 10 || - || -1 || 0 || Dp2HdmiFwUpdateNotice&lt;br /&gt;
|-&lt;br /&gt;
| 11 || 2 || 0 || 2 || PdcHFwVerRequest&lt;br /&gt;
|-&lt;br /&gt;
| 12 || - || 1 || 3 || PdcHFwVerReply&lt;br /&gt;
|-&lt;br /&gt;
| 13 || - || -1 || 0 || PdcHFwUpdateRequest&lt;br /&gt;
|-&lt;br /&gt;
| 14 || - || -1 || 0 || PdcHFwUpdateReply&lt;br /&gt;
|-&lt;br /&gt;
| 15 || - || -1 || 0 || PdcHFwUpdateNotice&lt;br /&gt;
|-&lt;br /&gt;
| 16 || 3 || 0 || 2 || PdcAFwVerRequest&lt;br /&gt;
|-&lt;br /&gt;
| 17 || - || 1 || 3 || PdcAFwVerReply&lt;br /&gt;
|-&lt;br /&gt;
| 18 || - || -1 || 0 || PdcAFwUpdateRequest&lt;br /&gt;
|-&lt;br /&gt;
| 19 || - || -1 || 0 || PdcAFwUpdateReply&lt;br /&gt;
|-&lt;br /&gt;
| 20 || - || -1 || 0 || PdcAFwUpdateNotice&lt;br /&gt;
|-&lt;br /&gt;
| 21 || - || 0 || 3 || DeviceErrorNotice&lt;br /&gt;
|-&lt;br /&gt;
| 22 || 4 || 0 || 2 || DeviceStateRequest&lt;br /&gt;
|-&lt;br /&gt;
| 23 || - || 1 || 3 || DeviceStateReply&lt;br /&gt;
|-&lt;br /&gt;
| 24 || 5 || 0 || 2 || McuFwVerRequest&lt;br /&gt;
|-&lt;br /&gt;
| 25 || - || 1 || 3 || McuFwVerReply&lt;br /&gt;
|-&lt;br /&gt;
| 26 || 6 || 0 || 2 || McuFwUpdateRequest&lt;br /&gt;
|-&lt;br /&gt;
| 27 || - || 1 || 2 || McuFwUpdateReply&lt;br /&gt;
|-&lt;br /&gt;
| 28 || 7 || 0 || 2 || UsbHubSleepRequest&lt;br /&gt;
|-&lt;br /&gt;
| 29 || - || 1 || 2 || UsbHubSleepReply&lt;br /&gt;
|-&lt;br /&gt;
| 30 || 8 || 0 || 2 || UsbHubResetRequest&lt;br /&gt;
|-&lt;br /&gt;
| 31 || - || 1 || 2 || UsbHubResetReply&lt;br /&gt;
|-&lt;br /&gt;
| 32 || 9 || 0 || 2 || UsbHubControlRequest&lt;br /&gt;
|-&lt;br /&gt;
| 33 || - || 1 || 2 || UsbHubControlReply&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= VdmCommandType =&lt;br /&gt;
This is &amp;quot;nn::usb::pd::driver::detail::VdmCommandType&amp;quot;.&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 || Name&lt;br /&gt;
|-&lt;br /&gt;
| -1 || None&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Initiator&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Ack&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Nak&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Busy&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UsbPowerState =&lt;br /&gt;
This is &amp;quot;nn::usb::UsbPowerState&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || [[#UsbPowerRole|UsbPowerRole]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || [[#UsbChargerType|UsbChargerType]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || Voltage&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || Current&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x4 || [[#Pdo|Pdo]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 0x4 || [[#Rdo|Rdo]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UsbPowerRole =&lt;br /&gt;
This is &amp;quot;nn::usb::UsbPowerRole&amp;quot;.&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 || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Sink&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Source&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UsbChargerType =&lt;br /&gt;
This is &amp;quot;nn::usb::UsbChargerType&amp;quot;.&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 || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Pd&lt;br /&gt;
|-&lt;br /&gt;
| 2 || TypeC15&lt;br /&gt;
|-&lt;br /&gt;
| 3 || TypeC30&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Dcp&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Cdp&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Sdp&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Apple500&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Apple1000&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Apple2000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SupplyType =&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Fixed&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Battery&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Variable&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Pdo =&lt;br /&gt;
When [[#SupplyType|SupplyType]] is Fixed this is:&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-9&lt;br /&gt;
| MaximumCurrent&lt;br /&gt;
|-&lt;br /&gt;
| 10-19&lt;br /&gt;
| Voltage&lt;br /&gt;
|-&lt;br /&gt;
| 20-21&lt;br /&gt;
| PeakCurrent&lt;br /&gt;
|-&lt;br /&gt;
| 22-24&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 25&lt;br /&gt;
| DataRoleSwap&lt;br /&gt;
|-&lt;br /&gt;
| 26&lt;br /&gt;
| UsbCommunicationsCapable&lt;br /&gt;
|-&lt;br /&gt;
| 27&lt;br /&gt;
| ExternallyPowered&lt;br /&gt;
|-&lt;br /&gt;
| 28&lt;br /&gt;
| UsbSuspendSupported&lt;br /&gt;
|-&lt;br /&gt;
| 29&lt;br /&gt;
| DualRolePower&lt;br /&gt;
|-&lt;br /&gt;
| 30-31&lt;br /&gt;
| [[#SupplyType|SupplyType]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When [[#SupplyType|SupplyType]] is Battery this is:&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-9&lt;br /&gt;
| MaximumAllowablePower&lt;br /&gt;
|-&lt;br /&gt;
| 10-19&lt;br /&gt;
| MinimumVoltage&lt;br /&gt;
|-&lt;br /&gt;
| 20-29&lt;br /&gt;
| MaximumVoltage&lt;br /&gt;
|-&lt;br /&gt;
| 30-31&lt;br /&gt;
| [[#SupplyType|SupplyType]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When [[#SupplyType|SupplyType]] is Variable this is:&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-9&lt;br /&gt;
| MaximumCurrent&lt;br /&gt;
|-&lt;br /&gt;
| 10-19&lt;br /&gt;
| MinimumVoltage&lt;br /&gt;
|-&lt;br /&gt;
| 20-29&lt;br /&gt;
| MaximumVoltage&lt;br /&gt;
|-&lt;br /&gt;
| 30-31&lt;br /&gt;
| [[#SupplyType|SupplyType]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Rdo =&lt;br /&gt;
When Pdo&#039;s [[#SupplyType|SupplyType]] is Fixed or Variable this is:&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-9&lt;br /&gt;
| MaximumOperatingCurrent (GiveBackFlag is true) or MinimumOperatingCurrent (GiveBackFlag is false)&lt;br /&gt;
|-&lt;br /&gt;
| 10-19&lt;br /&gt;
| OperatingCurrent&lt;br /&gt;
|-&lt;br /&gt;
| 20-23&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 24&lt;br /&gt;
| NoUsbSuspend&lt;br /&gt;
|-&lt;br /&gt;
| 25&lt;br /&gt;
| UsbCommunicationsCapable&lt;br /&gt;
|-&lt;br /&gt;
| 26&lt;br /&gt;
| CapabilityMismatch&lt;br /&gt;
|-&lt;br /&gt;
| 27&lt;br /&gt;
| GiveBackFlag&lt;br /&gt;
|-&lt;br /&gt;
| 28-30&lt;br /&gt;
| ObjectPosition&lt;br /&gt;
|-&lt;br /&gt;
| 31&lt;br /&gt;
| Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When Pdo&#039;s [[#SupplyType|SupplyType]] is Battery this is:&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-9&lt;br /&gt;
| MaximumOperatingPower (GiveBackFlag is true) or MinimumOperatingPower (GiveBackFlag is false)&lt;br /&gt;
|-&lt;br /&gt;
| 10-19&lt;br /&gt;
| OperatingPower&lt;br /&gt;
|-&lt;br /&gt;
| 20-23&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 24&lt;br /&gt;
| NoUsbSuspend&lt;br /&gt;
|-&lt;br /&gt;
| 25&lt;br /&gt;
| UsbCommunicationsCapable&lt;br /&gt;
|-&lt;br /&gt;
| 26&lt;br /&gt;
| CapabilityMismatch&lt;br /&gt;
|-&lt;br /&gt;
| 27&lt;br /&gt;
| GiveBackFlag&lt;br /&gt;
|-&lt;br /&gt;
| 28-30&lt;br /&gt;
| ObjectPosition&lt;br /&gt;
|-&lt;br /&gt;
| 31&lt;br /&gt;
| Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= UsbDataRole =&lt;br /&gt;
This is &amp;quot;nn::usb::UsbDataRole&amp;quot;.&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 || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 1 || DFP&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UFP&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= HidGamepad =&lt;br /&gt;
With [7.0.0+] usb-sysmodule now has .json data embedded in the codebin.&lt;br /&gt;
&lt;br /&gt;
This contains a list of USB devices&#039; VID/PID, with the following structure:&lt;br /&gt;
&lt;br /&gt;
  [&lt;br /&gt;
      {&lt;br /&gt;
          &amp;quot;vid&amp;quot; : &amp;quot;&amp;lt;VID&amp;gt;&amp;quot;,&lt;br /&gt;
          &amp;quot;pid&amp;quot; : &amp;quot;&amp;lt;PID&amp;gt;&amp;quot;,&lt;br /&gt;
          &amp;quot;quirks&amp;quot; : [&lt;br /&gt;
              {&lt;br /&gt;
                  &amp;quot;name&amp;quot; : &amp;quot;&amp;lt;string&amp;gt;&amp;quot; //The .json has the following for &amp;lt;string&amp;gt; for various devices: &amp;quot;HidGamepadWhitelist&amp;quot;, &amp;quot;ApplicationBlacklist&amp;quot;, and &amp;quot;NoClearHaltOnEpInit&amp;quot;.&lt;br /&gt;
              }&lt;br /&gt;
              //There can be multiple entries here.&lt;br /&gt;
          ]&lt;br /&gt;
      },&lt;br /&gt;
      &amp;lt;more entries&amp;gt;&lt;br /&gt;
  ]&lt;br /&gt;
&lt;br /&gt;
[12.1.0+]: The following entries were added in this json, all of which have quirks set for &amp;quot;HidGamepadWhitelist&amp;quot;.&lt;br /&gt;
** vid &amp;quot;0F0D&amp;quot;, where pid is &amp;quot;0200&amp;quot; - &amp;quot;022F&amp;quot;.&lt;br /&gt;
** vid &amp;quot;33DD&amp;quot;, where pid is &amp;quot;0001&amp;quot; - &amp;quot;000B&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[22.5.0+]: An entry for vid &amp;quot;3958&amp;quot; + pid &amp;quot;1900&amp;quot; was added, where quirks contains &amp;quot;HidGamepadWhitelist&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
= Configuration =&lt;br /&gt;
The following is the default USB config strings, while the usbds service isn&#039;t being used. All of the below configuration will reset to the defaults when all usbds-related sessions are closed. These can be set with [[#SetVidPidBcd]]. The default string for Product is loaded from [[Settings_services|settings]] config. The default is referred to by usb-sysmodule as &amp;quot;Dummy&amp;quot;.&lt;br /&gt;
  Product: Nintendo Switch&lt;br /&gt;
  Manufacturer: Nintendo&lt;br /&gt;
  SerialNumber: SerialNumber&lt;br /&gt;
&lt;br /&gt;
The following is the default &amp;lt;code&amp;gt;lsusb -v {...}&amp;lt;/code&amp;gt; output when the usbds service wasn&#039;t used.&lt;br /&gt;
&lt;br /&gt;
pre-5.0.0: The endpoints are configured using [[#RegisterEndpoint]], the total number of endpoints is the number of open [[#IDsEndpoint]] sessions. bInterfaceNumber is {0-based index for the enabled [[#IDsInterface]] session.} Some of the interface fields are configured using [[#RegisterInterface]].&lt;br /&gt;
&lt;br /&gt;
When usbds is in use where [[#SetVidPidBcd]] wasn&#039;t used, the VID/PID is 057e:3000.&lt;br /&gt;
&lt;br /&gt;
  Bus 003 Device 006: ID 057e:2000 Nintendo Co., Ltd &lt;br /&gt;
  Couldn&#039;t open device, some information will be missing&lt;br /&gt;
  Device Descriptor:&lt;br /&gt;
    bLength                18&lt;br /&gt;
    bDescriptorType         1&lt;br /&gt;
    bcdUSB               2.00&lt;br /&gt;
    bDeviceClass            0 (Defined at Interface level)&lt;br /&gt;
    bDeviceSubClass         0 &lt;br /&gt;
    bDeviceProtocol         0 &lt;br /&gt;
    bMaxPacketSize0        64&lt;br /&gt;
    idVendor           0x057e Nintendo Co., Ltd&lt;br /&gt;
    idProduct          0x2000 &lt;br /&gt;
    bcdDevice            1.00&lt;br /&gt;
    iManufacturer           1 &lt;br /&gt;
    iProduct                2 &lt;br /&gt;
    iSerial                 3 &lt;br /&gt;
    bNumConfigurations      1&lt;br /&gt;
    Configuration Descriptor:&lt;br /&gt;
      bLength                 9&lt;br /&gt;
      bDescriptorType         2&lt;br /&gt;
      wTotalLength           34&lt;br /&gt;
      bNumInterfaces          1&lt;br /&gt;
      bConfigurationValue     1&lt;br /&gt;
      iConfiguration          0 &lt;br /&gt;
      bmAttributes         0xc0&lt;br /&gt;
        Self Powered&lt;br /&gt;
      MaxPower              {...}&lt;br /&gt;
      Interface Descriptor:&lt;br /&gt;
        bLength                 9&lt;br /&gt;
        bDescriptorType         4&lt;br /&gt;
        bInterfaceNumber        0&lt;br /&gt;
        bAlternateSetting       0&lt;br /&gt;
        bNumEndpoints           1&lt;br /&gt;
        bInterfaceClass         3 Human Interface Device&lt;br /&gt;
        bInterfaceSubClass      0 No Subclass&lt;br /&gt;
        bInterfaceProtocol      0 None&lt;br /&gt;
        iInterface              0 &lt;br /&gt;
          HID Device Descriptor:&lt;br /&gt;
            bLength                 9&lt;br /&gt;
            bDescriptorType        33&lt;br /&gt;
            bcdHID               2.00&lt;br /&gt;
            bCountryCode            0 Not supported&lt;br /&gt;
            bNumDescriptors         1&lt;br /&gt;
            bDescriptorType        34 Report&lt;br /&gt;
            wDescriptorLength      26&lt;br /&gt;
           Report Descriptors: &lt;br /&gt;
             ** UNAVAILABLE **&lt;br /&gt;
        Endpoint Descriptor:&lt;br /&gt;
          bLength                 7&lt;br /&gt;
          bDescriptorType         5&lt;br /&gt;
          bEndpointAddress     0x81  EP 1 IN&lt;br /&gt;
          bmAttributes            3&lt;br /&gt;
            Transfer Type            Interrupt&lt;br /&gt;
            Synch Type               None&lt;br /&gt;
            Usage Type               Data&lt;br /&gt;
          wMaxPacketSize     0x0001  1x 1 bytes&lt;br /&gt;
          bInterval              16&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.5.0&amp;diff=14778</id>
		<title>22.5.0</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=22.5.0&amp;diff=14778"/>
		<updated>2026-06-16T20:10:03Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* System Titles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Switch 22.5.0 system update was released on June 16, 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;
*   &lt;br /&gt;
*     The Nintendo eShop layout has been redesigned.&lt;br /&gt;
*     	&lt;br /&gt;
*           The Nintendo eShop color will now reflect the theme color if your theme in System Settings is set to “Basic Dark.”&lt;br /&gt;
*       &lt;br /&gt;
*     &lt;br /&gt;
*     User-Verification PIN can now be used to confirm when “Accessing Nintendo eShop” and “Using Saved Payment Methods.”&lt;br /&gt;
*     Added the ability to rewind 10 seconds/advance 10 seconds with the ZL and ZR Buttons when watching a full screen video in News or Nintendo eShop.&lt;br /&gt;
*     General system stability improvements to enhance the user&#039;s experience.&lt;br /&gt;
*    &lt;br /&gt;
&lt;br /&gt;
==System Titles==&lt;br /&gt;
* The following titles were updated:&lt;br /&gt;
** Sysmodules: usb, settings, bsdsocket, hid, wlan, account, ns, am, ssl, erpt, es, migration.&lt;br /&gt;
** SystemData (non-sysver): BrowserDll, Help, FirmwareDebugSettings, BootImagePackage, BootImagePackageSafe, BootImagePackageExFat, BootImagePackageExFatSafe, ClientCertData.&lt;br /&gt;
** Applets: qlaunch, auth, error, playerSelect, swkbd, LibAppletOff, myPage, splay, systemWeb, openWeb.&lt;br /&gt;
&lt;br /&gt;
[[NPDM]] changes (besides usual version-bump):&lt;br /&gt;
* LibAppletOff: Service access: removed bsd:a, bsdcfg, htcs:sys, nifm:u.&lt;br /&gt;
* systemWeb: Service access: removed htcs:sys.&lt;br /&gt;
* openWeb: Service access: removed htcs:sys.&lt;br /&gt;
&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* BrowserDll:&lt;br /&gt;
** &amp;quot;/browser/RootCaEtc.pem&amp;quot; updated&lt;br /&gt;
** &amp;quot;/buildinfo/buildinfo.dat&amp;quot; updated&lt;br /&gt;
** &amp;quot;/gfxShader/MediaPlayerDrawer.bnsh&amp;quot; updated&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/lyt/ImageViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/Lion.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/MediaViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/nro/netfront/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/cruiser.bfsar&amp;quot; updated&lt;br /&gt;
* Help: &amp;quot;/legallines.htdocs/index.html&amp;quot; updated&lt;br /&gt;
* [[System_Version_Title|SystemVersion]]: All files updated.&lt;br /&gt;
* [[System_Settings|FirmwareDebugSettings]]: All files updated.&lt;br /&gt;
* ClientCertData: All files updated.&lt;br /&gt;
* qlaunch applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/qlaunch_action.bksnd&amp;quot; updated&lt;br /&gt;
* auth applet: &amp;quot;/message/USen/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USfr/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USpt/common.msbt.szs&amp;quot; updated&lt;br /&gt;
* error applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* playerSelect applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* swkbd applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/swkbd_action.bksnd&amp;quot; updated&lt;br /&gt;
* [[Internet_Browser|LibAppletOff applet]]: All files updated.&lt;br /&gt;
* myPage applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/myPage_action.bksnd&amp;quot; updated&lt;br /&gt;
* systemWeb applet: All files updated.&lt;br /&gt;
* openWeb applet: All files updated.&lt;br /&gt;
* splay applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
&lt;br /&gt;
=== BootImagePackages ===&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* &amp;quot;/nx/package2&amp;quot; updated&lt;br /&gt;
&lt;br /&gt;
Only the KIPs were updated:&lt;br /&gt;
* FS&lt;br /&gt;
* Loader, only the anti-downgrade list.&lt;br /&gt;
* NCM was rebuilt (BuildId updated).&lt;br /&gt;
&lt;br /&gt;
=== [[USB_services|usb]] ===&lt;br /&gt;
Essentially only the [[USB_services#HidGamepad|HidGamepad]] json was updated.&lt;br /&gt;
&lt;br /&gt;
=== [[Settings_services|settings]] ===&lt;br /&gt;
Support for OSM was added for [[Settings_services#ProductModelName|ProductModelName]]/[[Settings_services#ProductModel|ProductModel]].&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-06-16_01-01-38&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=Settings_services&amp;diff=14777</id>
		<title>Settings services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Settings_services&amp;diff=14777"/>
		<updated>2026-06-16T19:47:54Z</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 related to the USB HID keyboard.&lt;br /&gt;
&lt;br /&gt;
The returned buffer consists of a 0x20-byte header followed by an array of key mapping structures.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || Magic number? (0x01000001)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x4 || Entry count per key (3 for US English, 4 for German as it includes AltGr mappings)&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x4 || Map count&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || Layout ID (e.g. 3 = German QWERTZ)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 0x10 || Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x8 * MapCount || Array of &amp;lt;code&amp;gt;KeyMapEntry&amp;lt;/code&amp;gt; structures. Indexed by the standard USB HID Usage ID (Keyboard/Keypad page 0x07).&lt;br /&gt;
|-&lt;br /&gt;
| ... || ... || Padding (remaining space up to 0x1000)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== KeyMapEntry ===&lt;br /&gt;
Structure defining the output characters and modifier behaviors for a single physical key. Size may vary depending on the symbol count per key.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&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 || Normal char: UTF-16 code point when no modifiers are pressed. Dead keys map directly to Unicode combining characters (like U+0301 for combining acute accent).&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || 0x2 || Flags: Bitmask for character behavior and modifier rules.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || 0x2 || Shift char: UTF-16 code point emitted when Shift is held.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6 || 0x2 || AltGr char: UTF-16 code point emitted when AltGr is held (only included if the &#039;entry count per key&#039; = 4)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Flags field changes how state changes are handled (like Caps Lock or NumLock) for that specific code point:&lt;br /&gt;
* 0x1001: Standard character. Uses standard Shift and Caps Lock rules.&lt;br /&gt;
* 0x1000: Static/dead character (e.g., Space).&lt;br /&gt;
* 0x20FF: Keypad modifier. State influenced by NumLock.&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;
== GetDeviceTimeZoneLocationName ==&lt;br /&gt;
No input, returns an output [[Glue_services#LocationName|LocationName]].&lt;br /&gt;
&lt;br /&gt;
== SetDeviceTimeZoneLocationName ==&lt;br /&gt;
Takes an input [[Glue_services#LocationName|LocationName]], 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;
= TvUnderscan =&lt;br /&gt;
This is s32. It defines the percentage point reduction from a 100% baseline.&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|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;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Invalid&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Nx&lt;br /&gt;
|-&lt;br /&gt;
| 2 || NxCopper&lt;br /&gt;
|-&lt;br /&gt;
| 3 || NxIowa&lt;br /&gt;
|-&lt;br /&gt;
| 4 || NxHoag&lt;br /&gt;
|-&lt;br /&gt;
| 5 || NxCalcio&lt;br /&gt;
|-&lt;br /&gt;
| 6 || NxAula&lt;br /&gt;
|-&lt;br /&gt;
| 7 || ([[#ProductModelName|ProductModelName]] BEE)&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [22.5.0+] ([[#ProductModelName|ProductModelName]] OSM)&lt;br /&gt;
|-&lt;br /&gt;
| 9 || &lt;br /&gt;
|-&lt;br /&gt;
| 10 || &lt;br /&gt;
|-&lt;br /&gt;
| 11 || &lt;br /&gt;
|-&lt;br /&gt;
| 12 || &lt;br /&gt;
|}&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;
= 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;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! [[#ProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HAC&amp;quot; || 1 &lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HAD&amp;quot; || 3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HDH&amp;quot; || 4&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;HEG&amp;quot; || 6 &lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;BEE&amp;quot; || 7&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;OSM&amp;quot; || [22.5.0+] 8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= SystemConfiguration =&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=22.5.0&amp;diff=14776</id>
		<title>22.5.0</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=22.5.0&amp;diff=14776"/>
		<updated>2026-06-16T19:43:24Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* System Titles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Switch 22.5.0 system update was released on June 16, 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;
*   &lt;br /&gt;
*     The Nintendo eShop layout has been redesigned.&lt;br /&gt;
*     	&lt;br /&gt;
*           The Nintendo eShop color will now reflect the theme color if your theme in System Settings is set to “Basic Dark.”&lt;br /&gt;
*       &lt;br /&gt;
*     &lt;br /&gt;
*     User-Verification PIN can now be used to confirm when “Accessing Nintendo eShop” and “Using Saved Payment Methods.”&lt;br /&gt;
*     Added the ability to rewind 10 seconds/advance 10 seconds with the ZL and ZR Buttons when watching a full screen video in News or Nintendo eShop.&lt;br /&gt;
*     General system stability improvements to enhance the user&#039;s experience.&lt;br /&gt;
*    &lt;br /&gt;
&lt;br /&gt;
==System Titles==&lt;br /&gt;
* The following titles were updated:&lt;br /&gt;
** Sysmodules: usb, settings, bsdsocket, hid, wlan, account, ns, am, ssl, erpt, es, migration.&lt;br /&gt;
** SystemData (non-sysver): BrowserDll, Help, FirmwareDebugSettings, BootImagePackage, BootImagePackageSafe, BootImagePackageExFat, BootImagePackageExFatSafe, ClientCertData.&lt;br /&gt;
** Applets: qlaunch, auth, error, playerSelect, swkbd, LibAppletOff, myPage, splay, systemWeb, openWeb.&lt;br /&gt;
&lt;br /&gt;
[[NPDM]] changes (besides usual version-bump):&lt;br /&gt;
* LibAppletOff: Service access: removed bsd:a, bsdcfg, htcs:sys, nifm:u.&lt;br /&gt;
* systemWeb: Service access: removed htcs:sys.&lt;br /&gt;
* openWeb: Service access: removed htcs:sys.&lt;br /&gt;
&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* BrowserDll:&lt;br /&gt;
** &amp;quot;/browser/RootCaEtc.pem&amp;quot; updated&lt;br /&gt;
** &amp;quot;/buildinfo/buildinfo.dat&amp;quot; updated&lt;br /&gt;
** &amp;quot;/gfxShader/MediaPlayerDrawer.bnsh&amp;quot; updated&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/lyt/ImageViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/Lion.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/MediaViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/nro/netfront/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/cruiser.bfsar&amp;quot; updated&lt;br /&gt;
* Help: &amp;quot;/legallines.htdocs/index.html&amp;quot; updated&lt;br /&gt;
* [[System_Version_Title|SystemVersion]]: All files updated.&lt;br /&gt;
* [[System_Settings|FirmwareDebugSettings]]: All files updated.&lt;br /&gt;
* ClientCertData: All files updated.&lt;br /&gt;
* qlaunch applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/qlaunch_action.bksnd&amp;quot; updated&lt;br /&gt;
* auth applet: &amp;quot;/message/USen/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USfr/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USpt/common.msbt.szs&amp;quot; updated&lt;br /&gt;
* error applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* playerSelect applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* swkbd applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/swkbd_action.bksnd&amp;quot; updated&lt;br /&gt;
* [[Internet_Browser|LibAppletOff applet]]: All files updated.&lt;br /&gt;
* myPage applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/myPage_action.bksnd&amp;quot; updated&lt;br /&gt;
* systemWeb applet: All files updated.&lt;br /&gt;
* openWeb applet: All files updated.&lt;br /&gt;
* splay applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
&lt;br /&gt;
=== BootImagePackages ===&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* &amp;quot;/nx/package2&amp;quot; updated&lt;br /&gt;
&lt;br /&gt;
Only the KIPs were updated:&lt;br /&gt;
* FS&lt;br /&gt;
* Loader, only the anti-downgrade list.&lt;br /&gt;
* NCM was rebuilt (BuildId updated).&lt;br /&gt;
&lt;br /&gt;
=== [[Settings_services|settings]] ===&lt;br /&gt;
Support for OSM was added for [[Settings_services#ProductModelName|ProductModelName]]/[[Settings_services#ProductModel|ProductModel]].&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-06-16_01-01-38&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=22.5.0&amp;diff=14775</id>
		<title>22.5.0</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=22.5.0&amp;diff=14775"/>
		<updated>2026-06-16T01:45:24Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* BootImagePackages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Switch 22.5.0 system update was released on June 16, 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;
*   &lt;br /&gt;
*     The Nintendo eShop layout has been redesigned.&lt;br /&gt;
*     	&lt;br /&gt;
*           The Nintendo eShop color will now reflect the theme color if your theme in System Settings is set to “Basic Dark.”&lt;br /&gt;
*       &lt;br /&gt;
*     &lt;br /&gt;
*     User-Verification PIN can now be used to confirm when “Accessing Nintendo eShop” and “Using Saved Payment Methods.”&lt;br /&gt;
*     Added the ability to rewind 10 seconds/advance 10 seconds with the ZL and ZR Buttons when watching a full screen video in News or Nintendo eShop.&lt;br /&gt;
*     General system stability improvements to enhance the user&#039;s experience.&lt;br /&gt;
*    &lt;br /&gt;
&lt;br /&gt;
==System Titles==&lt;br /&gt;
* The following titles were updated:&lt;br /&gt;
** Sysmodules: usb, settings, bsdsocket, hid, wlan, account, ns, am, ssl, erpt, es, migration.&lt;br /&gt;
** SystemData (non-sysver): BrowserDll, Help, FirmwareDebugSettings, BootImagePackage, BootImagePackageSafe, BootImagePackageExFat, BootImagePackageExFatSafe, ClientCertData.&lt;br /&gt;
** Applets: qlaunch, auth, error, playerSelect, swkbd, LibAppletOff, myPage, splay, systemWeb, openWeb.&lt;br /&gt;
&lt;br /&gt;
[[NPDM]] changes (besides usual version-bump):&lt;br /&gt;
* LibAppletOff: Service access: removed bsd:a, bsdcfg, htcs:sys, nifm:u.&lt;br /&gt;
* systemWeb: Service access: removed htcs:sys.&lt;br /&gt;
* openWeb: Service access: removed htcs:sys.&lt;br /&gt;
&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* BrowserDll:&lt;br /&gt;
** &amp;quot;/browser/RootCaEtc.pem&amp;quot; updated&lt;br /&gt;
** &amp;quot;/buildinfo/buildinfo.dat&amp;quot; updated&lt;br /&gt;
** &amp;quot;/gfxShader/MediaPlayerDrawer.bnsh&amp;quot; updated&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/lyt/ImageViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/Lion.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/lyt/MediaViewer.arc&amp;quot; added&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/nro/netfront/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/cruiser.bfsar&amp;quot; updated&lt;br /&gt;
* Help: &amp;quot;/legallines.htdocs/index.html&amp;quot; updated&lt;br /&gt;
* [[System_Version_Title|SystemVersion]]: All files updated.&lt;br /&gt;
* [[System_Settings|FirmwareDebugSettings]]: All files updated.&lt;br /&gt;
* ClientCertData: All files updated.&lt;br /&gt;
* qlaunch applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/qlaunch_action.bksnd&amp;quot; updated&lt;br /&gt;
* auth applet: &amp;quot;/message/USen/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USfr/common.msbt.szs&amp;quot; updated, &amp;quot;/message/USpt/common.msbt.szs&amp;quot; updated&lt;br /&gt;
* error applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* playerSelect applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
* swkbd applet:&lt;br /&gt;
** &amp;quot;/lyt/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/swkbd_action.bksnd&amp;quot; updated&lt;br /&gt;
* [[Internet_Browser|LibAppletOff applet]]: All files updated.&lt;br /&gt;
* myPage applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
** &amp;quot;/sound/myPage_action.bksnd&amp;quot; updated&lt;br /&gt;
* systemWeb applet: All files updated.&lt;br /&gt;
* openWeb applet: All files updated.&lt;br /&gt;
* splay applet:&lt;br /&gt;
** &amp;quot;/message/&amp;quot;: Various data updated.&lt;br /&gt;
&lt;br /&gt;
=== BootImagePackages ===&lt;br /&gt;
RomFs changes:&lt;br /&gt;
* &amp;quot;/nx/package2&amp;quot; updated&lt;br /&gt;
&lt;br /&gt;
Only the KIPs were updated:&lt;br /&gt;
* FS&lt;br /&gt;
* Loader, only the anti-downgrade list.&lt;br /&gt;
* NCM was rebuilt (BuildId updated).&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-06-16_01-01-38&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=14727</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14727"/>
		<updated>2026-05-18T23:26:01Z</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 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;
The tmem_size must be at least 0x50EA80.&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;
The &amp;quot;nn::migration::device::IServer&amp;quot; version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.&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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
Takes a type-0x6 output buffer containing an array of a 0x128-byte struct, returns an output u32 total_out.&lt;br /&gt;
&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] AbortAsync2&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;
With [20.0.0+] [[LDN_services|ldn]] SetProtocol is used with a state field (Protocol3). It&#039;s unknown whether the protocol changes later during S2-only savedata transfer.&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 (zeros).&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x90 || [21.0.1+]&lt;br /&gt;
|-&lt;br /&gt;
| 0x91 || [-21.0.0]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x398-byte struct.&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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== 0x90 ====&lt;br /&gt;
This replaced DataMessageId 0x91 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
The initial response following the header 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;
| 0x0 || 0x8 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== 0x91 ====&lt;br /&gt;
This was replaced by DataMessageId 0x90 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
| 0x8 || 0x4 || s32&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || s32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Initial response data, after the DataMessageId:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;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 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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, with false indicating the request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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 || Below struct.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0x20-byte struct 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;
| 0x8 || 0x8 || InitialDataVersion2 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 0x8 || Size&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], which the client then imports. This begins with the [[Filesystem_services|InitialDataVersion2]] (with size from [[#PrepareTransfer2|PrepareTransfer2]]), with the rest being the savedata-export.&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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14726</id>
		<title>Network</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Network&amp;diff=14726"/>
		<updated>2026-05-18T17:29:10Z</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 expires_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;
*** The rest of the fields are likely only used with &amp;quot;nn::migration::device::*&amp;quot; (?).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/%s&amp;quot;:&lt;br /&gt;
** The POST data is empty.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld&amp;quot;:&lt;br /&gt;
** This is used following certain network requests which failed, depending on the Result. In one case it&#039;s used without a prior network request.&lt;br /&gt;
** No POST data (?).&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start.&lt;br /&gt;
*** Most usage of this will return 0 instead of the Result from the request which failed, when status is the expected value and expires_at&amp;gt;0.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/register_destination&amp;quot;:&lt;br /&gt;
** The json POST data contains the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;dst_device_appearance_main&amp;quot;:&amp;quot;&amp;lt;str0&amp;gt;&amp;quot;,&amp;quot;dst_device_appearance_controller&amp;quot;:&amp;quot;&amp;lt;str1&amp;gt;&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;str0&amp;gt;/&amp;lt;str1&amp;gt; are the same as with &amp;quot;/start&amp;quot;.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/save_datas/%lld/generate_key_seed_package&amp;quot; / &amp;quot;/%lld/generate_key_seed_package&amp;quot;:&lt;br /&gt;
** The json POST data contains the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;challenge&amp;quot;:&amp;quot;%s&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Where %s is the 0x10-byte challenge ([[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision GetChallenge]]) printed with &amp;quot;%02x&amp;quot; for each byte.&lt;br /&gt;
** The json response is parsed as the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;key_seed_package&amp;quot;:&amp;lt;str&amp;gt;,&amp;quot;error&amp;quot;:&amp;lt;...&amp;gt;,&amp;quot;code&amp;quot;:&amp;lt;str&amp;gt;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** When the HTTP status is 200, the key_seed_package string is base64 decoded. The output is then later used with [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision SetKeySeedPackage]].&lt;br /&gt;
*** Otherwise, the value of the &amp;quot;code&amp;quot; string is compared against a table, to determine the Result to return. (&amp;quot;error&amp;quot; is unused?)&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=Network&amp;diff=14725</id>
		<title>Network</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Network&amp;diff=14725"/>
		<updated>2026-05-18T17:28:09Z</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 expires_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;
*** The rest of the fields are likely only used with &amp;quot;nn::migration::device::*&amp;quot; (?).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/%s&amp;quot;:&lt;br /&gt;
** The POST data is empty.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld&amp;quot;:&lt;br /&gt;
** This is used following certain network requests which failed, depending on the Result. In one case it&#039;s used without a prior network request.&lt;br /&gt;
** No POST data (?).&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start.&lt;br /&gt;
*** Most usage of this will return 0 instead of the Result from the request which failed, when status is the expected value and expires_at&amp;gt;0.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/register_destination&amp;quot;:&lt;br /&gt;
** The json POST data contains the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;dst_device_appearance_main&amp;quot;:&amp;quot;&amp;lt;str0&amp;gt;&amp;quot;,&amp;quot;dst_device_appearance_controller&amp;quot;:&amp;quot;&amp;lt;str1&amp;gt;&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;str0&amp;gt;/&amp;lt;str1&amp;gt; are the same as with &amp;quot;/start&amp;quot;.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/save_datas/%lld/generate_key_seed_package&amp;quot; / &amp;quot;/%lld/generate_key_seed_package&amp;quot;:&lt;br /&gt;
** The json POST data contains the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;challenge&amp;quot;:&amp;quot;%s&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Where %s is the 0x10-byte challenge ([[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision GetChallenge]]) printed with &amp;quot;%02x&amp;quot; for each byte.&lt;br /&gt;
** The json response is parsed as the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;key_seed_package&amp;quot;:&amp;lt;str&amp;gt;,&amp;quot;error&amp;quot;:{...},&amp;quot;code&amp;quot;:&amp;lt;str&amp;gt;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** When the HTTP status is 200, the key_seed_package string is base64 decoded. The output is then later used with [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision SetKeySeedPackage]].&lt;br /&gt;
*** Otherwise, the value of the &amp;quot;code&amp;quot; string is compared against a table, to determine the Result to return. (&amp;quot;error&amp;quot; is unused?)&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=14724</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14724"/>
		<updated>2026-05-18T05:26:43Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* PrepareTransferDisconnect2 */&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;
The tmem_size must be at least 0x50EA80.&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;
The &amp;quot;nn::migration::device::IServer&amp;quot; version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.&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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
Takes a type-0x6 output buffer containing an array of a 0x128-byte struct, returns an output u32 total_out.&lt;br /&gt;
&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] AbortAsync2&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;
With [20.0.0+] [[LDN_services|ldn]] SetProtocol is used with a state field (Protocol3). It&#039;s unknown whether the protocol changes later during S2-only savedata transfer.&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 (zeros).&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x90 || [21.0.1+]&lt;br /&gt;
|-&lt;br /&gt;
| 0x91 || [-21.0.0]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x398-byte struct.&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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== 0x90 ====&lt;br /&gt;
This replaced DataMessageId 0x91 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
The initial response following the header 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;
| 0x0 || 0x8 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== 0x91 ====&lt;br /&gt;
This was replaced by DataMessageId 0x90 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
| 0x8 || 0x4 || s32&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || s32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Initial response data, after the DataMessageId:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;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 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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, with false indicating the request is used.&lt;br /&gt;
&lt;br /&gt;
The response only contains the 0x4-byte header.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14721</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14721"/>
		<updated>2026-05-17T02:27:09Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* Protocol */&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;
The tmem_size must be at least 0x50EA80.&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;
The &amp;quot;nn::migration::device::IServer&amp;quot; version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.&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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
Takes a type-0x6 output buffer containing an array of a 0x128-byte struct, returns an output u32 total_out.&lt;br /&gt;
&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] AbortAsync2&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;
With [20.0.0+] [[LDN_services|ldn]] SetProtocol is used with a state field (Protocol3). It&#039;s unknown whether the protocol changes later during S2-only savedata transfer.&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 (zeros).&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x90 || [21.0.1+]&lt;br /&gt;
|-&lt;br /&gt;
| 0x91 || [-21.0.0]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x398-byte struct.&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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== 0x90 ====&lt;br /&gt;
This replaced DataMessageId 0x91 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
The initial response following the header 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;
| 0x0 || 0x8 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== 0x91 ====&lt;br /&gt;
This was replaced by DataMessageId 0x90 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
| 0x8 || 0x4 || s32&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || s32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Initial response data, after the DataMessageId:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;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 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14720</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14720"/>
		<updated>2026-05-16T23:48:42Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* CreateSaveDataMigrationClient */&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;
The tmem_size must be at least 0x50EA80.&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;
The &amp;quot;nn::migration::device::IServer&amp;quot; version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.&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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
Takes a type-0x6 output buffer containing an array of a 0x128-byte struct, returns an output u32 total_out.&lt;br /&gt;
&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] AbortAsync2&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 (zeros).&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x90 || [21.0.1+]&lt;br /&gt;
|-&lt;br /&gt;
| 0x91 || [-21.0.0]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x398-byte struct.&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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== 0x90 ====&lt;br /&gt;
This replaced DataMessageId 0x91 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
The initial response following the header 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;
| 0x0 || 0x8 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== 0x91 ====&lt;br /&gt;
This was replaced by DataMessageId 0x90 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
| 0x8 || 0x4 || s32&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || s32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Initial response data, after the DataMessageId:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;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 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14719</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14719"/>
		<updated>2026-05-16T23:38:20Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* ListServers */&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;
The &amp;quot;nn::migration::device::IServer&amp;quot; version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.&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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
Takes a type-0x6 output buffer containing an array of a 0x128-byte struct, returns an output u32 total_out.&lt;br /&gt;
&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] AbortAsync2&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 (zeros).&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x90 || [21.0.1+]&lt;br /&gt;
|-&lt;br /&gt;
| 0x91 || [-21.0.0]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x398-byte struct.&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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== 0x90 ====&lt;br /&gt;
This replaced DataMessageId 0x91 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
The initial response following the header 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;
| 0x0 || 0x8 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== 0x91 ====&lt;br /&gt;
This was replaced by DataMessageId 0x90 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
| 0x8 || 0x4 || s32&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || s32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Initial response data, after the DataMessageId:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;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 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14712</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14712"/>
		<updated>2026-05-16T19:28:49Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* KeyExchange */&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;
The &amp;quot;nn::migration::device::IServer&amp;quot; version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.&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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] AbortAsync2&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 (zeros).&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x90 || [21.0.1+]&lt;br /&gt;
|-&lt;br /&gt;
| 0x91 || [-21.0.0]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x398-byte struct.&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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== 0x90 ====&lt;br /&gt;
This replaced DataMessageId 0x91 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
The initial response following the header 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;
| 0x0 || 0x8 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== 0x91 ====&lt;br /&gt;
This was replaced by DataMessageId 0x90 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
| 0x8 || 0x4 || s32&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || s32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Initial response data, after the DataMessageId:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;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 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14711</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14711"/>
		<updated>2026-05-16T02:54:15Z</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;
The &amp;quot;nn::migration::device::IServer&amp;quot; version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.&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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] AbortAsync2&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x90 || [21.0.1+]&lt;br /&gt;
|-&lt;br /&gt;
| 0x91 || [-21.0.0]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x398-byte struct.&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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== 0x90 ====&lt;br /&gt;
This replaced DataMessageId 0x91 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
The initial response following the header 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;
| 0x0 || 0x8 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== 0x91 ====&lt;br /&gt;
This was replaced by DataMessageId 0x90 with [21.0.1+]. This is used by &amp;quot;nn::migration::device::IServer&amp;quot; ProcessTransferAsync.&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;
| 0x8 || 0x4 || s32&lt;br /&gt;
|-&lt;br /&gt;
| 0xC || 0x4 || s32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Initial response data, after the DataMessageId:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;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 || 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. (Album related)&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14709</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14709"/>
		<updated>2026-05-15T22:45: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 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;
The &amp;quot;nn::migration::device::IServer&amp;quot; version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.&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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#WaitConnectionAsync|WaitConnectionAsync]]&lt;br /&gt;
|-&lt;br /&gt;
| 230 || &lt;br /&gt;
|-&lt;br /&gt;
| 290 || &lt;br /&gt;
|-&lt;br /&gt;
| 300 || ProcessTransferAsync&lt;br /&gt;
|-&lt;br /&gt;
| 400 || CompleteAsync&lt;br /&gt;
|-&lt;br /&gt;
| 510 || [20.0.0-20.5.0]&lt;br /&gt;
|-&lt;br /&gt;
| 511 || [21.0.0+] AbortAsync2&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x398-byte struct.&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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14708</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14708"/>
		<updated>2026-05-14T19:58:10Z</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;
The &amp;quot;nn::migration::device::IServer&amp;quot; version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.&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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#WaitConnectionAsync|WaitConnectionAsync]]&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x398-byte struct.&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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14707</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14707"/>
		<updated>2026-05-14T15:05: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 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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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;
With &amp;quot;nn::migration::device::&amp;quot; this is a 0x218-byte struct.&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14705</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14705"/>
		<updated>2026-05-13T15:03:58Z</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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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 (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):&lt;br /&gt;
&lt;br /&gt;
[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;
! 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 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x104 || 0x4 || [20.0.0+] [[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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14704</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14704"/>
		<updated>2026-05-13T03:44: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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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. Index in the fs data used by [[#GetList|GetList]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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. Index in the fs data used by [[#GetList|GetList]].&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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14703</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14703"/>
		<updated>2026-05-13T03:34: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. 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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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;
| 0x80 || [[#Transfer|Transfer]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]&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. &amp;gt;=3 is invalid.&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;
==== Transfer ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.&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;
The initial response payload message following the header 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;
| 0x0 || 0x8 || &lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || 0x8 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.&lt;br /&gt;
&lt;br /&gt;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&lt;br /&gt;
&lt;br /&gt;
The request only contains the header.&lt;br /&gt;
&lt;br /&gt;
The initial response payload message following the header 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;
| 0x0 || 0x8 || Zeros&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The remaining messages contain the transfer payload.&lt;br /&gt;
&lt;br /&gt;
With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14702</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14702"/>
		<updated>2026-05-12T23:52: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+] [[#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 [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] and sends the response.&lt;br /&gt;
** When the output bool from [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 [[#PrepareTransfer2|PrepareTransfer2]] 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 [[#Transfer2|Transfer2]] 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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&lt;br /&gt;
* If a state flag is not set, a func is called:&lt;br /&gt;
** Uses network message [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]].&lt;br /&gt;
** If the state fields checked by [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&lt;br /&gt;
* Uses network message [[#PrepareTransfer2|PrepareTransfer2]]. 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 [[#PrepareTransfer2|PrepareTransfer2]]: +0x18 and +0x8.&lt;br /&gt;
* Calls a func, for loading data from the above entry.&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 [[#Transfer2|Transfer2]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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 || [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE1 || [[#PrepareTransfer2|PrepareTransfer2]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xE2 || [[#Transfer2|Transfer2]]&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. &amp;gt;=3 is invalid.&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;
==== PrepareTransferDisconnect2 ====&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;
==== PrepareTransfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] 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;
==== Transfer2 ====&lt;br /&gt;
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].&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]], 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 (from &amp;quot;nn::migration::savedata::*&amp;quot;) 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=14701</id>
		<title>Network</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Network&amp;diff=14701"/>
		<updated>2026-05-12T21:37:50Z</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 expires_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;
*** The rest of the fields are likely only used with &amp;quot;nn::migration::device::*&amp;quot; (?).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/%s&amp;quot;:&lt;br /&gt;
** The POST data is empty.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld&amp;quot;:&lt;br /&gt;
** This is used following certain network requests which failed, depending on the Result. In one case it&#039;s used without a prior network request.&lt;br /&gt;
** No POST data (?).&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start.&lt;br /&gt;
*** Most usage of this will return 0 instead of the Result from the request which failed, when status is the expected value and expires_at&amp;gt;0.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/register_destination&amp;quot;:&lt;br /&gt;
** The json POST data contains the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;dst_device_appearance_main&amp;quot;:&amp;quot;&amp;lt;str0&amp;gt;&amp;quot;,&amp;quot;dst_device_appearance_controller&amp;quot;:&amp;quot;&amp;lt;str1&amp;gt;&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;str0&amp;gt;/&amp;lt;str1&amp;gt; are the same as with &amp;quot;/start&amp;quot;.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/save_datas/%lld/generate_key_seed_package&amp;quot; / &amp;quot;/%lld/generate_key_seed_package&amp;quot;:&lt;br /&gt;
** The json POST data contains the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;challenge&amp;quot;:&amp;quot;%s&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Where %s is the 0x10-byte challenge ([[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision GetChallenge]]) printed with &amp;quot;%02x&amp;quot; for each byte.&lt;br /&gt;
** The response is parsed as follows (HTTP status must be 200):&lt;br /&gt;
*** This is base64 decoded. The output is then later used with [[Filesystem_services#ISaveDataTransferManagerWithDivision|ISaveDataTransferManagerWithDivision SetKeySeedPackage]].&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=Network&amp;diff=14700</id>
		<title>Network</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Network&amp;diff=14700"/>
		<updated>2026-05-12T21:01:21Z</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 expires_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;
*** The rest of the fields are likely only used with &amp;quot;nn::migration::device::*&amp;quot; (?).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/%s&amp;quot;:&lt;br /&gt;
** The POST data is empty.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld&amp;quot;:&lt;br /&gt;
** This is used following certain network requests which failed, depending on the Result. In one case it&#039;s used without a prior network request.&lt;br /&gt;
** No POST data (?).&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start.&lt;br /&gt;
*** Most usage of this will return 0 instead of the Result from the request which failed, when status is the expected value and expires_at&amp;gt;0.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/register_destination&amp;quot;:&lt;br /&gt;
** The json POST data contains the following:&lt;br /&gt;
*** &amp;lt;code&amp;gt;{&amp;quot;dst_device_appearance_main&amp;quot;:&amp;quot;&amp;lt;str0&amp;gt;&amp;quot;,&amp;quot;dst_device_appearance_controller&amp;quot;:&amp;quot;&amp;lt;str1&amp;gt;&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &amp;lt;str0&amp;gt;/&amp;lt;str1&amp;gt; are the same as with &amp;quot;/start&amp;quot;.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&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=Network&amp;diff=14699</id>
		<title>Network</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Network&amp;diff=14699"/>
		<updated>2026-05-12T20:02:26Z</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 expires_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;
*** The rest of the fields are likely only used with &amp;quot;nn::migration::device::*&amp;quot; (?).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/%s&amp;quot;:&lt;br /&gt;
** The POST data is empty.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld&amp;quot;:&lt;br /&gt;
** This is used following certain network requests which failed, depending on the Result. In one case it&#039;s used without a prior network request.&lt;br /&gt;
** No POST data (?).&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start.&lt;br /&gt;
*** Most usage of this will return 0 instead of the Result from the request which failed, when status is the expected value and expires_at&amp;gt;0.&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=Network&amp;diff=14698</id>
		<title>Network</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Network&amp;diff=14698"/>
		<updated>2026-05-12T16:54:10Z</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 expires_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;
*** The rest of the fields are likely only used with &amp;quot;nn::migration::device::*&amp;quot; (?).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/%s&amp;quot;:&lt;br /&gt;
** The POST data is empty.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** This is parsed similar to /start above. The minimum required fields are the same as /start. The rest of the output is unused.&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=Network&amp;diff=14697</id>
		<title>Network</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Network&amp;diff=14697"/>
		<updated>2026-05-12T15:07:46Z</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;
*** The rest of the fields are likely only used with &amp;quot;nn::migration::device::*&amp;quot; (?).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/%lld/%s&amp;quot;:&lt;br /&gt;
** The POST data is empty.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** {...}&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=Network&amp;diff=14689</id>
		<title>Network</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Network&amp;diff=14689"/>
		<updated>2026-05-09T03:26:47Z</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;
* &amp;quot;/%lld/%s&amp;quot;:&lt;br /&gt;
** The POST data is empty.&lt;br /&gt;
** The json response is parsed as the following (HTTP status must be 200):&lt;br /&gt;
*** {...}&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=14688</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14688"/>
		<updated>2026-05-09T01:22:45Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* AbortAsync2 */&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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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]]. If this code-path is used it also sets the Result returned later to 0.&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&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, for loading data from the above entry.&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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. &amp;gt;=3 is invalid.&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=14687</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14687"/>
		<updated>2026-05-09T01:06:41Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* AbortAsync2 */&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 false (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 the [[#GetTransferEventId|transfer_event_id]], if this wasn&#039;t set yet this 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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&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, for loading data from the above entry.&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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. &amp;gt;=3 is invalid.&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=Error_codes&amp;diff=14686</id>
		<title>Error codes</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Error_codes&amp;diff=14686"/>
		<updated>2026-05-08T22:05:33Z</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/ Console Permanent Ban]&lt;br /&gt;
|-&lt;br /&gt;
| 0x23387C || 124 || 4508 || [https://en-americas-support.nintendo.com/app/answers/detail/a_id/28046/ Console Permanent Ban]&lt;br /&gt;
|-&lt;br /&gt;
| 0x234A7C || 124 || 4517 || [https://en-americas-support.nintendo.com/app/answers/detail/a_id/43652/ Console 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;
| 0x82CCA || 202 || 1046 || AppletResourceUserId is already registered.&lt;br /&gt;
|-&lt;br /&gt;
| 0x82ECA || 202 || 1047 || Invalid AppletResourceUserId.&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=14685</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14685"/>
		<updated>2026-05-08T18:09:59Z</updated>

		<summary type="html">&lt;p&gt;Yellows8: /* ConnectByServerIdAsync */&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;
* Calls a func to get the data which is sent with SendClientProfile below.&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. This loops through the fs data previously received by [[#GetList|GetList]], to sum the size field (entry+0x4) with each entry. Once finished this updates state then writes data into a separate fs file.&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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&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, for loading data from the above entry.&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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. &amp;gt;=3 is invalid.&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=14684</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14684"/>
		<updated>2026-05-08T17:22:56Z</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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&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 to read the current entry, from the fs data previously received with [[#GetList|GetList]].&lt;br /&gt;
* Calls a func which validates the entry data output from the above func (u8 +0x0).&lt;br /&gt;
* Logs a report with [[PSC_services|srepo]]. Includes data from the above entry, etc.&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, for loading data from the above entry.&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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. &amp;gt;=3 is invalid.&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=14683</id>
		<title>Migration services</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Migration_services&amp;diff=14683"/>
		<updated>2026-05-08T16:42: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 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. Depending on state this may call a func which:&lt;br /&gt;
** Loops through the fs data previously received by [[#GetList|GetList]]. With each entry, calls a func. This uses [[Filesystem_services|FindSaveDataWithFilter]] and uses the output with [[NS_services|IApplicationManagerInterface DeleteSaveData]].&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. This loops through the fs data previously received by [[#GetList|GetList]]. With each entry, uses [[NS_services|IApplicationVersionInterface UpgradeLaunchRequiredVersion]] with the data from the entry. Uses [[OLSC_services|IRemoteStorageController]] cmd28, then when successful uses [[OLSC_services|IRemoteStorageController GetLoadedDataInfo]]. Then [[OLSC_services|IOlscServiceForSystemService SetUserSaveDataProperty]] is used with the entry data. Once finished, it also uses [[OLSC_services|IDaemonController RunTransferTaskAutonomyRegistration]].&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:&lt;br /&gt;
* Calls a vfunc. When ret is true:&lt;br /&gt;
** Calls a vfunc. When ret is true, calls the same func for UpgradeLaunchRequiredVersion as [[#CompleteAsync_2|CompleteAsync]].&lt;br /&gt;
** Otherwise when false:&lt;br /&gt;
*** Calls a vfunc.&lt;br /&gt;
*** Calls the same savedata-deletion func as [[#TransferNextAsync|TransferNextAsync]].&lt;br /&gt;
* Calls vfuncs.&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=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>
</feed>