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*