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