xref: /openbmc/google-misc/subprojects/ncsid/src/platforms/nemora/portable/ncsi_server.c (revision dab96f131fb3a46d93f1093feccc9095d8589ece)
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