Line 31: |
Line 31: |
| | ... || || [[#Buffer descriptor A/B/W "Send"/"Receive"/"Exchange"|Buf B descriptors]], each one 3 words. | | | ... || || [[#Buffer descriptor A/B/W "Send"/"Receive"/"Exchange"|Buf B descriptors]], each one 3 words. |
| |- | | |- |
− | | ... || || [[#Buffer descriptor A/B/W "Send"/"Receive"/"Exchange"|Type W descriptors]], each one 3 words. | + | | ... || || [[#Buffer descriptor A/B/W "Send"/"Receive"/"Exchange"|Buf W descriptors]], each one 3 words. |
| |- | | |- |
| | ... || || [[#Raw_data_section|Raw data section]] (including padding before and after aligned data section). | | | ... || || [[#Raw_data_section|Raw data section]] (including padding before and after aligned data section). |
Line 172: |
Line 172: |
| Used to enforce whether or not device mapping is allowed for src and dst buffers respectively. | | Used to enforce whether or not device mapping is allowed for src and dst buffers respectively. |
| | | |
− | * Flag0: Device mapping *not* allowed for src or dst. | + | * Ipc (flag=0): Device mapping *not* allowed for src or dst. |
− | * Flag1: Device mapping allowed for src and dst. | + | * NonSecureIpc (flag=1): Device mapping allowed for src and dst. |
− | * Flag3: Device mapping allowed for src but not for dst. | + | * NonDeviceIpc (flag=3): Device mapping allowed for src but not for dst. |
| | | |
| === Buffer descriptor C "ReceiveList" === | | === Buffer descriptor C "ReceiveList" === |
Line 289: |
Line 289: |
| | | |
| == Official marshalling code == | | == Official marshalling code == |
− | The official marshalling function takes an array of (buf_ptr, size) pairs and a type-field for each such pair. | + | The official marshalling function is called "nn::sf::hipc::client::Hipc2ClientCoreProcessorImpl::WriteBufferDataImpl" and takes: |
− | | + | * A pointer to a "nn::sf::hipc::detail::HipcMessageWriter" context; |
− | Bitmask 0x10 seems to indicate null-terminated strings.
| + | * The number of (buf_ptr, size) pairs; |
| + | * An array of (buf_ptr, size) pairs (called "nn::sf::detail::PointerAndSize"); |
| + | * A pointer to a type bitfield for each such pair; |
| + | * The offset of the main IPC command structure; |
| + | * The size of the IPC command's [[IPC_Marshalling#Raw_data_section|raw data]]. |
| | | |
| + | The type of an IPC command is described by a bitfield as below: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
− | ! Type Mask || Description || Direction | + | ! Bits || Description |
− | |-
| |
− | | 4 + 1 || Creates a A descriptor with flags=0. || In
| |
− | |-
| |
− | | 0x40 + 4 + 1 || Creates a A descriptor with flags=1. || In
| |
− | |-
| |
− | | 0x80 + 4 + 1 || Creates a A descriptor with flags=3. || In
| |
| |- | | |- |
− | | 4 + 2 || Creates a B descriptor with flags=0. || Out | + | | 0 || Direction is input. |
| |- | | |- |
− | | 0x40 + 4 + 2 || Creates a B descriptor with flags=1. || Out | + | | 1 || Direction is output. |
| |- | | |- |
− | | 0x80 + 4 + 2 || Creates a B descriptor with flags=3. || Out | + | | 2 || Use buffer descriptors A ("Send"), B ("Receive") or W ("Exchange"). |
| |- | | |- |
− | | 8 + 1 || Creates an X descriptor || In | + | | 3 || Use buffer descriptors X ("Pointer") or C ("ReceiveList"). |
| |- | | |- |
− | | 8 + 2 || Creates a C descriptor, and writes the u16 size to an offset into raw data. || Out | + | | 4 || Skip saving the pointer buffer size in raw data. |
| |- | | |- |
− | | 0x10 + 8 + 2 || Creates a C descriptor || Out | + | | 5 || Select which buffer descriptor to use automatically. |
| |- | | |- |
− | | 0x20 + 1 || Creates both an A and X descriptor || In | + | | 6 || Use [[Flags|NonSecureIpc flag]]. |
| |- | | |- |
− | | 0x20 + 2 || Creates both an B and C descriptor || Out | + | | 7 || Use [[Flags|NonDeviceIpc flag]]. |
− | |-
| |
− | | 0x20 + 2 + 0x40 || Same as 0x20 + 2, except a certain value is set to hard-coded 0x1 instead. || Out
| |
| |} | | |} |
| | | |
| C and X (Pointer and ReceiveList) descriptors are backed by the "pointer buffer", a buffer in the service process. Its size is a u16, which is retrieved using the "QueryPointerBufferSize" control message. If the client code determines all buffers with flag 8 do not fit in the pointer buffer, it returns error 0x11A0B. | | C and X (Pointer and ReceiveList) descriptors are backed by the "pointer buffer", a buffer in the service process. Its size is a u16, which is retrieved using the "QueryPointerBufferSize" control message. If the client code determines all buffers with flag 8 do not fit in the pointer buffer, it returns error 0x11A0B. |
| | | |
− | For buffers with flag 0x20 it creates two descriptors (A+X or B+C), but one descriptor is NULL (zero size and pointer), while the other holds the expected values. X/C descriptors are used as the non-NULL descriptor where possible, but if they don't fit in the pointer buffer, A/B descriptors are used instead. The code defers processing of type 0x20 buffers with sizes that fit in a u16 (and may therefore fit in the pointer buffer). This ensures all type 8 buffers get pointer-buffer space before any type 0x20. | + | For buffers with flag 0x20 it creates two descriptors (A+X or B+C), but one descriptor is NULL (zero size and pointer), while the other holds the expected values. X/C descriptors are used as the non-NULL descriptor where possible, but if they don't fit in the pointer buffer, A/B descriptors are used instead. The code defers processing of type 0x20 buffers with sizes that fit in a u16 (and may therefore fit in the pointer buffer), which ensures all type 8 buffers get pointer-buffer space before any type 0x20. The order in which the deferred type 0x20 buffers are processed is determined by a convoluted loop. |
− | | |
− | (The order in which the deferred type 0x20 buffers are processed is determined by a convoluted loop.)
| |
| | | |
| == Official IPC Cmd Structure == | | == Official IPC Cmd Structure == |