blob: c7bc5e7cde904225730131b0a4964a5a4958a8a8 [file] [log] [blame]
William A. Kennington III7d6fa422021-02-08 17:04:02 -08001/*
2 * Library of NC-SI commands compliant with version 1.0.0.
3 *
4 * This implements a subset of the commands provided in the specification.
5 *
6 * Checksums are optional and not implemented here. All NC-SI checksums are set
7 * to 0 to indicate that per 8.2.2.3.
8 */
9
10#include <stdint.h>
11#include <string.h>
12
13#include <netinet/in.h>
14
15#include "platforms/nemora/portable/ncsi.h"
16#include "platforms/nemora/portable/ncsi_server.h"
17
18
19void ncsi_build_response_header(const uint8_t* request_buf,
20 uint8_t* response_buf, uint16_t response_code,
21 uint16_t reason_code, uint16_t payload_length) {
22 /* Copy the header from the command */
23 memcpy(response_buf, request_buf, sizeof(ncsi_header_t));
24 ncsi_simple_response_t* response = (ncsi_simple_response_t*)response_buf;
25 response->response_code = response_code;
26 response->reason_code = reason_code;
27
28 const ncsi_header_t* request_header = (const ncsi_header_t*)request_buf;
29 response->hdr.control_packet_type =
30 request_header->control_packet_type | NCSI_RESPONSE;
31 response->hdr.payload_length = htons(payload_length);
32}
33
34uint32_t ncsi_build_simple_ack(const uint8_t* request_buf,
35 uint8_t* response_buf) {
36 /* Copy the header from the command */
37 ncsi_build_response_header(
38 request_buf, response_buf, 0, 0,
39 sizeof(ncsi_simple_response_t) - sizeof(ncsi_header_t));
40
41 return sizeof(ncsi_simple_response_t);
42}
43
44uint32_t ncsi_build_simple_nack(const uint8_t* request_buf,
45 uint8_t* response_buf, uint16_t response_code,
46 uint16_t reason_code) {
47 ncsi_build_response_header(
48 request_buf, response_buf, response_code, reason_code,
49 sizeof(ncsi_simple_response_t) - sizeof(ncsi_header_t));
50
51 return sizeof(ncsi_simple_response_t);
52}
53
54static void ncsi_build_oem_ack(const uint8_t* request_buf,
55 uint8_t* response_buf, uint32_t response_size) {
56 ncsi_build_response_header(
57 request_buf, response_buf, 0, 0,
58 response_size - sizeof(ncsi_header_t));
59 const ncsi_oem_simple_cmd_t* oem_command =
60 (const ncsi_oem_simple_cmd_t*)request_buf;
61 ncsi_oem_simple_response_t* oem_response =
62 (ncsi_oem_simple_response_t*)response_buf;
63 memmove(&oem_response->oem_header, &oem_command->oem_header,
64 sizeof(ncsi_oem_extension_header_t));
65 oem_response->oem_header.manufacturer_id = htonl(NCSI_OEM_MANUFACTURER_ID);
66}
67
68uint32_t ncsi_build_version_id_ack(const uint8_t* request_buf,
69 uint8_t* response_buf,
70 const ncsi_version_id_t* version_id) {
71 ncsi_build_response_header(
72 request_buf, response_buf, 0, 0,
73 sizeof(ncsi_version_id_response_t) - sizeof(ncsi_header_t));
74 ncsi_version_id_response_t* version_id_response =
75 (ncsi_version_id_response_t*)response_buf;
76 memcpy(&version_id_response->version, version_id, sizeof(ncsi_version_id_t));
77 return sizeof(ncsi_version_id_response_t);
78}
79
80uint32_t ncsi_build_oem_get_mac_ack(const uint8_t* request_buf,
81 uint8_t* response_buf,
82 const mac_addr_t* mac) {
83 ncsi_build_oem_ack(request_buf, response_buf,
84 sizeof(ncsi_host_mac_response_t));
85 ncsi_host_mac_response_t* response = (ncsi_host_mac_response_t*)response_buf;
86 memcpy(response->mac, mac->octet, MAC_ADDR_SIZE);
87 return sizeof(ncsi_host_mac_response_t);
88}
89
90uint32_t ncsi_build_oem_simple_ack(const uint8_t* request_buf,
91 uint8_t* response_buf) {
92 ncsi_build_oem_ack(request_buf, response_buf,
93 sizeof(ncsi_oem_simple_response_t));
94 return sizeof(ncsi_oem_simple_response_t);
95}
96
97uint32_t ncsi_build_oem_echo_ack(const uint8_t* request_buf,
98 uint8_t* response_buf) {
99 ncsi_oem_echo_response_t* echo_response =
100 (ncsi_oem_echo_response_t*)response_buf;
101 const ncsi_oem_echo_cmd_t* echo_cmd = (const ncsi_oem_echo_cmd_t*)request_buf;
102 memmove(echo_response->pattern, echo_cmd->pattern, sizeof(echo_cmd->pattern));
103 // Because we allow request and response to be the same buffer, it is
104 // important that pattern copy precedes the call to ncsi_build_oem_ack.
105 ncsi_build_oem_ack(request_buf, response_buf,
106 sizeof(ncsi_oem_echo_response_t));
107
108 return sizeof(ncsi_oem_echo_response_t);
109}
110
111uint32_t ncsi_build_oem_get_filter_ack(const uint8_t* request_buf,
112 uint8_t* response_buf,
113 const ncsi_oem_filter_t* filter) {
114 ncsi_build_oem_ack(request_buf, response_buf,
115 sizeof(ncsi_oem_get_filter_response_t));
116 ncsi_oem_get_filter_response_t* get_filter_response =
117 (ncsi_oem_get_filter_response_t*)response_buf;
118 memcpy(&get_filter_response->filter, filter,
119 sizeof(get_filter_response->filter));
120 return sizeof(ncsi_oem_get_filter_response_t);
121}
122
123uint32_t ncsi_build_pt_stats_ack(const uint8_t* request_buf,
124 uint8_t* response_buf,
125 const ncsi_passthrough_stats_t* stats) {
126 ncsi_build_response_header(
127 request_buf, response_buf, 0, 0,
128 sizeof(ncsi_passthrough_stats_response_t) - sizeof(ncsi_header_t));
129 ncsi_passthrough_stats_response_t* pt_stats_response =
130 (ncsi_passthrough_stats_response_t*)response_buf;
131 /* TODO: endianness? */
132 memcpy(&pt_stats_response->stats, stats, sizeof(pt_stats_response->stats));
133 return sizeof(ncsi_passthrough_stats_response_t);
134}
135
136uint32_t ncsi_build_pt_stats_legacy_ack(
137 const uint8_t* request_buf, uint8_t* response_buf,
138 const ncsi_passthrough_stats_legacy_t* stats) {
139 ncsi_build_response_header(
140 request_buf, response_buf, 0, 0,
141 sizeof(ncsi_passthrough_stats_legacy_response_t) - sizeof(ncsi_header_t));
142 ncsi_passthrough_stats_legacy_response_t* pt_stats_response =
143 (ncsi_passthrough_stats_legacy_response_t*)response_buf;
144 /* TODO: endianness? */
145 memcpy(&pt_stats_response->stats, stats, sizeof(pt_stats_response->stats));
146 return sizeof(ncsi_passthrough_stats_legacy_response_t);
147}
148
149uint32_t ncsi_build_link_status_ack(const uint8_t* request_buf,
150 uint8_t* response_buf,
151 const ncsi_link_status_t* link_status) {
152 ncsi_build_response_header(
153 request_buf, response_buf, 0, 0,
154 sizeof(ncsi_link_status_response_t) - sizeof(ncsi_header_t));
155 ncsi_link_status_response_t* link_status_response =
156 (ncsi_link_status_response_t*)response_buf;
157 memcpy(&link_status_response->link_status, link_status,
158 sizeof(link_status_response->link_status));
159 return sizeof(ncsi_link_status_response_t);
160}