Migration services: Difference between revisions

No edit summary
 
(12 intermediate revisions by the same user not shown)
Line 121: Line 121:
== CreateSaveDataMigrationClient ==
== CreateSaveDataMigrationClient ==
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].
Takes an input u32 tmem_size, a type-0x19 input buffer containing a [[#ClientProfile|ClientProfile]], a TransferMemory handle, returns an [[#IClient_2|IClient]].
The tmem_size must be at least 0x50EA80.


== ResumeSaveDataMigrationClient ==
== ResumeSaveDataMigrationClient ==
Line 393: Line 395:
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.
** Calls a func. This receives [[#Suspend|Suspend]] or [[#SynchronizeState|SynchronizeState]] and sends the response.
* Updates a state flag and returns 0.
* Updates a state flag and returns 0.
The "nn::migration::device::IServer" version of this is roughly equivalent, except the funcs called after [[#RequestServerProfile|RequestServerProfile]] above are not used.


=== GetClientProductModel ===
=== GetClientProductModel ===
Line 571: Line 575:


=== ListServers ===
=== ListServers ===
Takes a type-0x6 output buffer containing an array of a 0x128-byte struct, returns an output u32 total_out.
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.
[20.0.0+] The struct size is now 0x130-bytes instead of 0x128-bytes.


Line 780: Line 786:
| 130 ||  
| 130 ||  
|-
|-
| 200 ||  
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]
|-
|-
| 230 ||  
| 230 ||  
Line 786: Line 792:
| 290 ||  
| 290 ||  
|-
|-
| 300 ||  
| 300 || ProcessTransferAsync
|-
|-
| 400 ||  
| 400 || CompleteAsync
|-
|-
| 510 || [20.0.0-20.5.0]
| 510 || [20.0.0-20.5.0]
|-
|-
| 511 || [21.0.0+]
| 511 || [21.0.0+] AbortAsync2
|-
|-
| 900 ||  
| 900 ||  
Line 1,014: Line 1,020:
= Protocol =
= Protocol =
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.
With [20.0.0+] [[LDN_services|ldn]] SetProtocol is used with a state field (Protocol3). It's unknown whether the protocol changes later during S2-only savedata transfer.


== AdvertiseData ==
== AdvertiseData ==
Line 1,178: Line 1,186:
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].
| 0x8 || 0x20 || Data from [[SPL_services|GenerateRandomBytes]].
|-
|-
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state.
| 0x28 || 0x10 || CMAC ([[SPL_services|ComputeCmac]]) over the above 0x20-bytes, followed by 0x20-bytes from state (zeros).
|}
|}


Line 1,327: Line 1,335:
| 0x20 || [[#AcceptDecline|AcceptDecline]]
| 0x20 || [[#AcceptDecline|AcceptDecline]]
|-
|-
| 0xE0 || [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]
| 0x80 || [[#Transfer|Transfer]]
|-
| 0x90 || [21.0.1+]
|-
| 0x91 || [-21.0.0]
|-
| 0xE0 || [20.0.0+] [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]]
|-
|-
| 0xE1 || [[#PrepareTransfer2|PrepareTransfer2]]
| 0xE1 || [20.0.0+] [[#PrepareTransfer2|PrepareTransfer2]]
|-
|-
| 0xE2 || [[#Transfer2|Transfer2]]
| 0xE2 || [20.0.0+] [[#Transfer2|Transfer2]]
|-
|-
| 0xF0 || [[#SynchronizeState|SynchronizeState]]
| 0xF0 || [[#SynchronizeState|SynchronizeState]]
Line 1,343: Line 1,357:
The request only contains the header.
The request only contains the header.


Response payload (0x148-byte struct, which has the following layout):
Response payload (0x140-byte struct ([20.0.0+] 0x148-byte), which has the following layout):
 
[20.0.0+]:


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 1,371: Line 1,387:
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]
| 0x144 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]
|}
|}
With "nn::migration::device::" this is a 0x398-byte struct.


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:
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:
Line 1,390: Line 1,408:
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]
| 0x0 || 0x100 || [[#ClientProfile|ClientProfile]]
|-
|-
| 0x100 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]
| 0x100 || 0x4 || [20.0.0+] [[Settings_services#GetProductModel|ProductModel]]
|-
|-
| 0x104 || 0x4 || [[System_Version_Title|SystemVersion]]. u32 in the form: <code>(Major<<16) | (Minor<<8) | Micro</code>
| 0x104 || 0x4 || [20.0.0+] [[System_Version_Title|SystemVersion]]. u32 in the form: <code>(Major<<16) | (Minor<<8) | Micro</code>
|}
|}
With "nn::migration::device::" this is a 0x218-byte struct.


The response only contains the header.
The response only contains the header.
Line 1,481: Line 1,501:
The response only contains the header.
The response only contains the header.


==== PrepareTransferDisconnect2 ====
==== Transfer ====
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]].
The client sends this via [[#TransferNextAsync|TransferNextAsync]]. With [20.0.0+] PrepareTransfer2/etc are used instead, for savedata.
 
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to <code>statefield==other_statefield</code>. This bool indicates whether the previously mentioned network request is used.
 
The response only contains the 0x4-byte header.
 
==== PrepareTransfer2 ====
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] if using it was enabled).


The request only contains the header, which besides the DataMessageId contains:
The request only contains the header, which besides the DataMessageId contains:
Line 1,497: Line 1,510:
! Offset || Size || Description
! Offset || Size || Description
|-
|-
| 0x4 || 0x4 || s32, must not be negative.
| 0x4 || 0x4 || s32, must not be negative. Index in the fs data used by [[#GetList|GetList]].
|}
|}


Response payload:
The initial response payload message following the header contains:


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 1,506: Line 1,519:
! Offset || Size || Description
! Offset || Size || Description
|-
|-
| 0x0 || 0x20 ||  
| 0x0 || 0x8 ||  
|-
|-
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]
| 0x8 || 0x8 ||  
|}
|}


==== Transfer2 ====
The remaining messages contain the transfer payload.
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].
 
The transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManager]], which the client then imports.


The request only contains the header.
==== 0x90 ====
This replaced DataMessageId 0x91 with [21.0.1+]. This is used by "nn::migration::device::IServer" ProcessTransferAsync.


Response payload:
The request only contains the header, which besides the DataMessageId contains:


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 1,522: Line 1,537:
! Offset || Size || Description
! Offset || Size || Description
|-
|-
| 0x0 || 0x8 || Zeros
| 0x4 || 0x4 || s32, must not be negative.
|}
 
The initial response following the header contains:
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
|-
| 0x8 || Rest of message || Transfer payload.
| 0x0 || 0x8 || Data size.
|}
|}


With savedata the transfer payload is the output from exporting savedata from [[Filesystem_services|ISaveDataTransferManagerWithDivision]], which the client then imports.
The remaining messages contain the data payload with the above size.
 
This is used for transferring the contents of a fs file. (Album related)
 
==== 0x91 ====
This was replaced by DataMessageId 0x90 with [21.0.1+]. This is used by "nn::migration::device::IServer" ProcessTransferAsync.
 
The request only contains the header, which besides the DataMessageId contains:
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x8 || 0x4 || s32
|-
| 0xC || 0x4 || s32
|}
 
Initial response data, after the DataMessageId:
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x4 || 0x4 || Data size.
|}
 
The remaining messages contain the data payload with the above size.
 
This is used for transferring the contents of a fs file. (Album related)
 
==== PrepareTransferDisconnect2 ====
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]].
 
The request only contains the 0x4-byte header. The bool at header+0x1 (after DataMessageId) is set to <code>statefield==other_statefield</code>. This bool indicates whether the previously mentioned network request is used, with false indicating the request is used.
 
The response only contains the 0x4-byte header.
 
==== PrepareTransfer2 ====
The client sends this via [[#TransferNextAsync|TransferNextAsync]] (after [[#PrepareTransferDisconnect2|PrepareTransferDisconnect2]] if using it was enabled).
 
The request only contains the header, which besides the DataMessageId contains:
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x4 || 0x4 || s32, must not be negative. Index in the fs data used by [[#GetList|GetList]].
|}
 
Response payload:
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x0 || 0x20 || Below struct.
|-
| 0x20 || 0x200 || [[Filesystem_services|LocalKeySeedPackage]]
|}
 
The 0x20-byte struct has the following layout:
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x8 || 0x8 || InitialDataVersion2 size
|-
| 0x18 || 0x8 || Size
|}
 
==== Transfer2 ====
The client sends this via [[#TransferNextAsync|TransferNextAsync]], after [[#PrepareTransfer2|PrepareTransfer2]].
 
The request only contains the header.
 
The initial response payload message following the header contains:
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x0 || 0x8 || Zeros
|}
 
The remaining messages contain the transfer payload.
 
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.


==== SynchronizeState ====
==== SynchronizeState ====