1 /*
2 * Copyright 2021 Google LLC
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * Library of NC-SI commands compliant with version 1.0.0.
19 *
20 * This implements a subset of the commands provided in the specification.
21 *
22 * Checksums are optional and not implemented here. All NC-SI checksums are set
23 * to 0 to indicate that per 8.2.2.3.
24 */
25
26 #include <stdint.h>
27 #include <string.h>
28
29 #include <netinet/in.h>
30
31 #include "platforms/nemora/portable/ncsi.h"
32 #include "platforms/nemora/portable/ncsi_server.h"
33
34
ncsi_build_response_header(const uint8_t * request_buf,uint8_t * response_buf,uint16_t response_code,uint16_t reason_code,uint16_t payload_length)35 void ncsi_build_response_header(const uint8_t* request_buf,
36 uint8_t* response_buf, uint16_t response_code,
37 uint16_t reason_code, uint16_t payload_length) {
38 /* Copy the header from the command */
39 memcpy(response_buf, request_buf, sizeof(ncsi_header_t));
40 ncsi_simple_response_t* response = (ncsi_simple_response_t*)response_buf;
41 response->response_code = response_code;
42 response->reason_code = reason_code;
43
44 const ncsi_header_t* request_header = (const ncsi_header_t*)request_buf;
45 response->hdr.control_packet_type =
46 request_header->control_packet_type | NCSI_RESPONSE;
47 response->hdr.payload_length = htons(payload_length);
48 }
49
ncsi_build_simple_ack(const uint8_t * request_buf,uint8_t * response_buf)50 uint32_t ncsi_build_simple_ack(const uint8_t* request_buf,
51 uint8_t* response_buf) {
52 /* Copy the header from the command */
53 ncsi_build_response_header(
54 request_buf, response_buf, 0, 0,
55 sizeof(ncsi_simple_response_t) - sizeof(ncsi_header_t));
56
57 return sizeof(ncsi_simple_response_t);
58 }
59
ncsi_build_simple_nack(const uint8_t * request_buf,uint8_t * response_buf,uint16_t response_code,uint16_t reason_code)60 uint32_t ncsi_build_simple_nack(const uint8_t* request_buf,
61 uint8_t* response_buf, uint16_t response_code,
62 uint16_t reason_code) {
63 ncsi_build_response_header(
64 request_buf, response_buf, response_code, reason_code,
65 sizeof(ncsi_simple_response_t) - sizeof(ncsi_header_t));
66
67 return sizeof(ncsi_simple_response_t);
68 }
69
ncsi_build_oem_ack(const uint8_t * request_buf,uint8_t * response_buf,uint32_t response_size)70 static void ncsi_build_oem_ack(const uint8_t* request_buf,
71 uint8_t* response_buf, uint32_t response_size) {
72 ncsi_build_response_header(
73 request_buf, response_buf, 0, 0,
74 response_size - sizeof(ncsi_header_t));
75 const ncsi_oem_simple_cmd_t* oem_command =
76 (const ncsi_oem_simple_cmd_t*)request_buf;
77 ncsi_oem_simple_response_t* oem_response =
78 (ncsi_oem_simple_response_t*)response_buf;
79 memmove(&oem_response->oem_header, &oem_command->oem_header,
80 sizeof(ncsi_oem_extension_header_t));
81 oem_response->oem_header.manufacturer_id = htonl(NCSI_OEM_MANUFACTURER_ID);
82 }
83
ncsi_build_version_id_ack(const uint8_t * request_buf,uint8_t * response_buf,const ncsi_version_id_t * version_id)84 uint32_t ncsi_build_version_id_ack(const uint8_t* request_buf,
85 uint8_t* response_buf,
86 const ncsi_version_id_t* version_id) {
87 ncsi_build_response_header(
88 request_buf, response_buf, 0, 0,
89 sizeof(ncsi_version_id_response_t) - sizeof(ncsi_header_t));
90 ncsi_version_id_response_t* version_id_response =
91 (ncsi_version_id_response_t*)response_buf;
92 memcpy(&version_id_response->version, version_id, sizeof(ncsi_version_id_t));
93 return sizeof(ncsi_version_id_response_t);
94 }
95
ncsi_build_oem_get_mac_ack(const uint8_t * request_buf,uint8_t * response_buf,const mac_addr_t * mac)96 uint32_t ncsi_build_oem_get_mac_ack(const uint8_t* request_buf,
97 uint8_t* response_buf,
98 const mac_addr_t* mac) {
99 ncsi_build_oem_ack(request_buf, response_buf,
100 sizeof(ncsi_host_mac_response_t));
101 ncsi_host_mac_response_t* response = (ncsi_host_mac_response_t*)response_buf;
102 memcpy(response->mac, mac->octet, MAC_ADDR_SIZE);
103 return sizeof(ncsi_host_mac_response_t);
104 }
105
ncsi_build_oem_simple_ack(const uint8_t * request_buf,uint8_t * response_buf)106 uint32_t ncsi_build_oem_simple_ack(const uint8_t* request_buf,
107 uint8_t* response_buf) {
108 ncsi_build_oem_ack(request_buf, response_buf,
109 sizeof(ncsi_oem_simple_response_t));
110 return sizeof(ncsi_oem_simple_response_t);
111 }
112
ncsi_build_oem_echo_ack(const uint8_t * request_buf,uint8_t * response_buf)113 uint32_t ncsi_build_oem_echo_ack(const uint8_t* request_buf,
114 uint8_t* response_buf) {
115 ncsi_oem_echo_response_t* echo_response =
116 (ncsi_oem_echo_response_t*)response_buf;
117 const ncsi_oem_echo_cmd_t* echo_cmd = (const ncsi_oem_echo_cmd_t*)request_buf;
118 memmove(echo_response->pattern, echo_cmd->pattern, sizeof(echo_cmd->pattern));
119 // Because we allow request and response to be the same buffer, it is
120 // important that pattern copy precedes the call to ncsi_build_oem_ack.
121 ncsi_build_oem_ack(request_buf, response_buf,
122 sizeof(ncsi_oem_echo_response_t));
123
124 return sizeof(ncsi_oem_echo_response_t);
125 }
126
ncsi_build_oem_get_filter_ack(const uint8_t * request_buf,uint8_t * response_buf,const ncsi_oem_filter_t * filter)127 uint32_t ncsi_build_oem_get_filter_ack(const uint8_t* request_buf,
128 uint8_t* response_buf,
129 const ncsi_oem_filter_t* filter) {
130 ncsi_build_oem_ack(request_buf, response_buf,
131 sizeof(ncsi_oem_get_filter_response_t));
132 ncsi_oem_get_filter_response_t* get_filter_response =
133 (ncsi_oem_get_filter_response_t*)response_buf;
134 memcpy(&get_filter_response->filter, filter,
135 sizeof(get_filter_response->filter));
136 return sizeof(ncsi_oem_get_filter_response_t);
137 }
138
ncsi_build_pt_stats_ack(const uint8_t * request_buf,uint8_t * response_buf,const ncsi_passthrough_stats_t * stats)139 uint32_t ncsi_build_pt_stats_ack(const uint8_t* request_buf,
140 uint8_t* response_buf,
141 const ncsi_passthrough_stats_t* stats) {
142 ncsi_build_response_header(
143 request_buf, response_buf, 0, 0,
144 sizeof(ncsi_passthrough_stats_response_t) - sizeof(ncsi_header_t));
145 ncsi_passthrough_stats_response_t* pt_stats_response =
146 (ncsi_passthrough_stats_response_t*)response_buf;
147 /* TODO: endianness? */
148 memcpy(&pt_stats_response->stats, stats, sizeof(pt_stats_response->stats));
149 return sizeof(ncsi_passthrough_stats_response_t);
150 }
151
ncsi_build_pt_stats_legacy_ack(const uint8_t * request_buf,uint8_t * response_buf,const ncsi_passthrough_stats_legacy_t * stats)152 uint32_t ncsi_build_pt_stats_legacy_ack(
153 const uint8_t* request_buf, uint8_t* response_buf,
154 const ncsi_passthrough_stats_legacy_t* stats) {
155 ncsi_build_response_header(
156 request_buf, response_buf, 0, 0,
157 sizeof(ncsi_passthrough_stats_legacy_response_t) - sizeof(ncsi_header_t));
158 ncsi_passthrough_stats_legacy_response_t* pt_stats_response =
159 (ncsi_passthrough_stats_legacy_response_t*)response_buf;
160 /* TODO: endianness? */
161 memcpy(&pt_stats_response->stats, stats, sizeof(pt_stats_response->stats));
162 return sizeof(ncsi_passthrough_stats_legacy_response_t);
163 }
164
ncsi_build_link_status_ack(const uint8_t * request_buf,uint8_t * response_buf,const ncsi_link_status_t * link_status)165 uint32_t ncsi_build_link_status_ack(const uint8_t* request_buf,
166 uint8_t* response_buf,
167 const ncsi_link_status_t* link_status) {
168 ncsi_build_response_header(
169 request_buf, response_buf, 0, 0,
170 sizeof(ncsi_link_status_response_t) - sizeof(ncsi_header_t));
171 ncsi_link_status_response_t* link_status_response =
172 (ncsi_link_status_response_t*)response_buf;
173 memcpy(&link_status_response->link_status, link_status,
174 sizeof(link_status_response->link_status));
175 return sizeof(ncsi_link_status_response_t);
176 }
177