| /* |
| * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & |
| * AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0 |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "diagnostics.h" |
| #include <endian.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| int encode_get_device_diagnostics_req(uint8_t instance_id, uint8_t segment_id, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_REQUEST; |
| header.instance_id = instance_id; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_get_device_diagnostics_req *request = |
| (struct nsm_get_device_diagnostics_req *)msg->payload; |
| |
| request->hdr.command = NSM_GET_DEVICE_DIAGNOSTICS; |
| request->hdr.data_size = sizeof(struct nsm_get_device_diagnostics_req) - |
| sizeof(struct nsm_common_req); |
| request->segment_id = segment_id; |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_get_device_diagnostics_req(const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *segment_id) |
| { |
| if (msg == NULL || segment_id == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (msg_len != sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_get_device_diagnostics_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_get_device_diagnostics_req *request = |
| (struct nsm_get_device_diagnostics_req *)msg->payload; |
| |
| if (request->hdr.data_size != |
| sizeof(struct nsm_get_device_diagnostics_req) - |
| sizeof(struct nsm_common_req)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *segment_id = request->segment_id; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_get_device_diagnostics_resp(uint8_t instance_id, uint8_t cc, |
| uint16_t reason_code, |
| const uint8_t *seg_data, |
| const uint16_t seg_data_size, |
| const uint8_t next_segment_id, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_RESPONSE; |
| header.instance_id = instance_id & INSTANCEID_MASK; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| if (cc != NSM_SUCCESS) { |
| return encode_reason_code(cc, reason_code, |
| NSM_GET_DEVICE_DIAGNOSTICS, msg); |
| } |
| |
| struct nsm_get_device_diagnostics_resp *response = |
| (struct nsm_get_device_diagnostics_resp *)msg->payload; |
| |
| response->hdr.command = NSM_GET_DEVICE_DIAGNOSTICS; |
| response->hdr.completion_code = cc; |
| response->hdr.data_size = |
| htole16(seg_data_size + sizeof(next_segment_id)); |
| response->next_segment_id = next_segment_id; |
| memcpy(response->segment_data, seg_data, seg_data_size); |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_get_device_diagnostics_resp(const struct nsm_msg *msg, |
| size_t msg_len, uint8_t *cc, |
| uint16_t *reason_code, uint8_t *seg_data, |
| uint16_t *seg_data_size, |
| uint8_t *next_segment_id) |
| { |
| if (seg_data == NULL || seg_data_size == NULL || |
| next_segment_id == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code); |
| if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) { |
| return rc; |
| } |
| |
| if (msg_len < sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_common_resp) + |
| sizeof(*next_segment_id)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_get_device_diagnostics_resp *response = |
| (struct nsm_get_device_diagnostics_resp *)msg->payload; |
| |
| if (response->hdr.data_size < sizeof(*next_segment_id)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *seg_data_size = |
| response->hdr.data_size - sizeof(response->next_segment_id); |
| *next_segment_id = response->next_segment_id; |
| memcpy(seg_data, response->segment_data, *seg_data_size); |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_reset_enum_data(uint8_t resetType, uint8_t *data, size_t *data_len) |
| { |
| if (data == NULL || data_len == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| *data = resetType; // Enum is 1 byte |
| *data_len = sizeof(uint8_t); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_reset_count_data(uint16_t count, uint8_t *data, size_t *data_len) |
| { |
| if (data == NULL || data_len == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| uint16_t le_count = htole16(count); |
| memcpy(data, &le_count, sizeof(uint16_t)); |
| *data_len = sizeof(uint16_t); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_reset_count_256data(const uint64_t *counter, uint8_t *data, |
| size_t *data_len) |
| { |
| if (data == NULL || data_len == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| for (size_t i = 0; i < 4; i++) { |
| uint64_t le_count = htole64(counter[i]); |
| memcpy(data + i * sizeof(uint64_t), &le_count, |
| sizeof(uint64_t)); |
| } |
| *data_len = sizeof(uint64_t) * 4; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_reset_enum_data(const uint8_t *data, size_t data_len, |
| uint8_t *resetType) |
| { |
| if (data == NULL || resetType == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (data_len != sizeof(uint8_t)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| *resetType = *data; // Enum is 1 byte |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_reset_count_data(const uint8_t *data, size_t data_len, |
| uint16_t *count) |
| { |
| if (data == NULL || count == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (data_len != sizeof(uint16_t)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| uint16_t le_count; |
| memcpy(&le_count, data, sizeof(uint16_t)); |
| *count = le16toh(le_count); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_reset_count_256data(const uint8_t *data, size_t data_len, |
| uint64_t *counter, size_t counter_len) |
| { |
| if (data == NULL || counter == NULL || counter_len != 4) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (data_len != sizeof(uint64_t) * counter_len) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| for (size_t i = 0; i < counter_len; i++) { |
| uint64_t le_count; |
| memcpy(&le_count, data + i * sizeof(uint64_t), |
| sizeof(uint64_t)); |
| counter[i] = le64toh(le_count); |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_get_device_reset_statistics_req(uint8_t instance_id, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_REQUEST; |
| header.instance_id = instance_id; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_common_req *request = (struct nsm_common_req *)msg->payload; |
| request->command = NSM_GET_DEVICE_RESET_STATISTICS; |
| request->data_size = 0; // No additional payload for the request |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_get_device_reset_statistics_req(const struct nsm_msg *msg, |
| size_t msg_len) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| // Validate message length |
| if (msg_len < |
| sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| // Cast the payload to nsm_common_req structure |
| const struct nsm_common_req *request = |
| (const struct nsm_common_req *)msg->payload; |
| |
| // Validate that the data_size field in the common request is 0 |
| // (indicating no extra data) |
| if (request->data_size != 0) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_reset_network_device_req(uint8_t instance_id, uint8_t mode, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_REQUEST; |
| header.instance_id = instance_id; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_reset_network_device_req *request = |
| (struct nsm_reset_network_device_req *)msg->payload; |
| |
| request->hdr.command = NSM_RESET_NETWORK_DEVICE; |
| request->hdr.data_size = sizeof(mode); |
| request->mode = mode; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_reset_network_device_req(const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *mode) |
| { |
| if (msg == NULL || mode == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (msg_len < sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_reset_network_device_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_reset_network_device_req *request = |
| (struct nsm_reset_network_device_req *)msg->payload; |
| |
| if (request->hdr.data_size < sizeof(request->mode)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *mode = request->mode; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_reset_network_device_resp(uint8_t instance_id, uint16_t reason_code, |
| struct nsm_msg *msg) |
| { |
| return encode_cc_only_resp(instance_id, NSM_TYPE_DIAGNOSTIC, |
| NSM_RESET_NETWORK_DEVICE, NSM_SUCCESS, |
| reason_code, msg); |
| } |
| |
| int decode_reset_network_device_resp(const struct nsm_msg *msg, size_t msgLen, |
| uint8_t *cc, uint16_t *reason_code) |
| { |
| int rc = decode_reason_code_and_cc(msg, msgLen, cc, reason_code); |
| if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) { |
| return rc; |
| } |
| |
| if (msgLen < sizeof(struct nsm_msg_hdr) + |
| sizeof(nsm_reset_network_device_resp)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| nsm_reset_network_device_resp *resp = |
| (nsm_reset_network_device_resp *)msg->payload; |
| if (resp->data_size != 0) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_enable_disable_wp_req( |
| uint8_t instance_id, |
| enum diagnostics_enable_disable_wp_data_index data_index, uint8_t value, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_REQUEST; |
| header.instance_id = instance_id; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_enable_disable_wp_req *request = |
| (struct nsm_enable_disable_wp_req *)msg->payload; |
| |
| request->hdr.command = NSM_ENABLE_DISABLE_WP; |
| request->hdr.data_size = 2; |
| request->data_index = data_index; |
| request->value = value; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_enable_disable_wp_req( |
| const struct nsm_msg *msg, size_t msg_len, |
| enum diagnostics_enable_disable_wp_data_index *data_index, uint8_t *value) |
| { |
| if (msg == NULL || data_index == NULL || value == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (msg_len < sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_enable_disable_wp_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_enable_disable_wp_req *request = |
| (struct nsm_enable_disable_wp_req *)msg->payload; |
| |
| if (request->hdr.data_size < sizeof(struct nsm_enable_disable_wp_req) - |
| NSM_REQUEST_CONVENTION_LEN) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *data_index = request->data_index; |
| *value = request->value; |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_enable_disable_wp_resp(uint8_t instance_id, uint8_t cc, |
| uint16_t reason_code, struct nsm_msg *msg) |
| { |
| return encode_common_resp(instance_id, cc, reason_code, |
| NSM_TYPE_DIAGNOSTIC, NSM_ENABLE_DISABLE_WP, |
| msg); |
| } |
| |
| int decode_enable_disable_wp_resp(const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *cc, uint16_t *reason_code) |
| { |
| uint16_t data_size = 0; |
| int rc = decode_common_resp(msg, msg_len, cc, &data_size, reason_code); |
| if (data_size != 0) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| return rc; |
| } |
| |
| int encode_get_network_device_debug_info_req(uint8_t instance_id, |
| uint8_t debug_type, |
| uint32_t handle, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_REQUEST; |
| header.instance_id = instance_id; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_get_network_device_debug_info_req *request = |
| (struct nsm_get_network_device_debug_info_req *)msg->payload; |
| |
| request->hdr.command = NSM_GET_NETWORK_DEVICE_DEBUG_INFO; |
| request->hdr.data_size = |
| sizeof(struct nsm_get_network_device_debug_info_req) - |
| sizeof(struct nsm_common_req); |
| request->debug_info_type = debug_type; |
| request->reserved = 0x00; |
| request->record_handle = htole32(handle); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_get_network_device_debug_info_req(const struct nsm_msg *msg, |
| size_t msg_len, |
| uint8_t *debug_type, |
| uint32_t *handle) |
| { |
| if (msg == NULL || debug_type == NULL || handle == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (msg_len < |
| sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_get_network_device_debug_info_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_get_network_device_debug_info_req *request = |
| (struct nsm_get_network_device_debug_info_req *)msg->payload; |
| |
| if (request->hdr.data_size != |
| sizeof(struct nsm_get_network_device_debug_info_req) - |
| sizeof(struct nsm_common_req)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *debug_type = request->debug_info_type; |
| *handle = le32toh(request->record_handle); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_get_network_device_debug_info_resp(uint8_t instance_id, uint8_t cc, |
| uint16_t reason_code, |
| const uint8_t *seg_data, |
| const uint16_t seg_data_size, |
| const uint32_t next_handle, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_RESPONSE; |
| header.instance_id = instance_id & INSTANCEID_MASK; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &msg->hdr); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| if (cc != NSM_SUCCESS) { |
| return encode_reason_code( |
| cc, reason_code, NSM_GET_NETWORK_DEVICE_DEBUG_INFO, msg); |
| } |
| |
| struct nsm_get_network_device_debug_info_resp *resp = |
| (struct nsm_get_network_device_debug_info_resp *)msg->payload; |
| |
| resp->hdr.command = NSM_GET_NETWORK_DEVICE_DEBUG_INFO; |
| resp->hdr.completion_code = cc; |
| |
| uint16_t total_data_size = seg_data_size + sizeof(next_handle); |
| resp->hdr.data_size = htole16(total_data_size); |
| resp->next_record_handle = htole32(next_handle); |
| |
| if (cc == NSM_SUCCESS) { |
| { |
| if (seg_data == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| } |
| memcpy(resp->segment_data, seg_data, seg_data_size); |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_get_network_device_debug_info_resp(const struct nsm_msg *msg, |
| size_t msg_len, uint8_t *cc, |
| uint16_t *reason_code, |
| uint16_t *seg_data_size, |
| uint8_t *seg_data, |
| uint32_t *next_handle) |
| { |
| if (seg_data == NULL || seg_data_size == NULL || next_handle == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code); |
| if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) { |
| return rc; |
| } |
| |
| if (msg_len < |
| sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_get_network_device_debug_info_resp) - |
| sizeof(uint8_t)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_get_network_device_debug_info_resp *resp = |
| (struct nsm_get_network_device_debug_info_resp *)msg->payload; |
| |
| uint16_t total_data_size = le16toh(resp->hdr.data_size); |
| *next_handle = le32toh(resp->next_record_handle); |
| *seg_data_size = total_data_size - sizeof(resp->next_record_handle); |
| |
| memcpy(seg_data, resp->segment_data, *seg_data_size); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_erase_trace_req(uint8_t instance_id, struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_REQUEST; |
| header.instance_id = instance_id; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_erase_trace_req *request = |
| (struct nsm_erase_trace_req *)msg->payload; |
| |
| request->hdr.command = NSM_ERASE_TRACE; |
| request->hdr.data_size = 0x00; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_erase_trace_req(const struct nsm_msg *msg, size_t msg_len) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (msg_len < |
| sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_erase_trace_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_erase_trace_req *request = |
| (struct nsm_erase_trace_req *)msg->payload; |
| |
| if (request->hdr.data_size != 0) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_erase_trace_resp(uint8_t instance_id, uint8_t cc, |
| uint16_t reason_code, uint8_t result_status, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_RESPONSE; |
| header.instance_id = instance_id & INSTANCEID_MASK; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &msg->hdr); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| if (cc != NSM_SUCCESS) { |
| return encode_reason_code(cc, reason_code, NSM_ERASE_TRACE, |
| msg); |
| } |
| |
| struct nsm_erase_trace_resp *response = |
| (struct nsm_erase_trace_resp *)msg->payload; |
| |
| response->hdr.command = NSM_ERASE_TRACE; |
| response->hdr.completion_code = cc; |
| response->hdr.data_size = htole16(sizeof(uint8_t)); |
| response->result_status = result_status; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_erase_trace_resp(const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *cc, uint16_t *reason_code, |
| uint8_t *result_status) |
| { |
| if (result_status == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code); |
| if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) { |
| return rc; |
| } |
| |
| if (msg_len != |
| sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_erase_trace_resp)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_erase_trace_resp *response = |
| (struct nsm_erase_trace_resp *)msg->payload; |
| |
| uint16_t data_size = le16toh(response->hdr.data_size); |
| if (data_size != sizeof(uint8_t)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *result_status = response->result_status; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_get_network_device_log_info_req(uint8_t instance_id, |
| uint32_t record_handle, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_REQUEST; |
| header.instance_id = instance_id; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_get_network_device_log_info_req *request = |
| (struct nsm_get_network_device_log_info_req *)msg->payload; |
| |
| request->hdr.command = NSM_GET_NETWORK_DEVICE_LOG_INFO; |
| request->hdr.data_size = |
| sizeof(struct nsm_get_network_device_log_info_req) - |
| sizeof(struct nsm_common_req); |
| request->record_handle = htole32(record_handle); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_get_network_device_log_info_req(const struct nsm_msg *msg, |
| size_t msg_len, |
| uint32_t *record_handle) |
| { |
| if (msg == NULL || record_handle == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (msg_len < sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_get_network_device_log_info_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_get_network_device_log_info_req *request = |
| (struct nsm_get_network_device_log_info_req *)msg->payload; |
| |
| if (request->hdr.data_size != |
| sizeof(struct nsm_get_network_device_log_info_req) - |
| sizeof(struct nsm_common_req)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *record_handle = le32toh(request->record_handle); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_get_network_device_log_info_resp( |
| uint8_t instance_id, uint8_t cc, uint16_t reason_code, |
| const uint32_t next_handle, |
| struct nsm_device_log_info_breakdown log_info_breakdown, |
| const uint8_t *log_data, const uint16_t log_data_size, struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_RESPONSE; |
| header.instance_id = instance_id & INSTANCEID_MASK; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &msg->hdr); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| if (cc != NSM_SUCCESS) { |
| return encode_reason_code(cc, reason_code, |
| NSM_GET_NETWORK_DEVICE_LOG_INFO, msg); |
| } |
| |
| struct nsm_get_network_device_log_info_resp *resp = |
| (struct nsm_get_network_device_log_info_resp *)msg->payload; |
| |
| resp->hdr.command = NSM_GET_NETWORK_DEVICE_LOG_INFO; |
| resp->hdr.completion_code = cc; |
| |
| uint16_t total_data_size = log_data_size + sizeof(next_handle) + |
| sizeof(struct nsm_device_log_info); |
| resp->hdr.data_size = htole16(total_data_size); |
| resp->next_record_handle = htole32(next_handle); |
| |
| struct nsm_device_log_info *log_info = |
| (struct nsm_device_log_info *)(&log_info_breakdown); |
| resp->log_info.lost_events_and_synced_time = |
| log_info->lost_events_and_synced_time; |
| resp->log_info.reserved1 = log_info->reserved1; |
| resp->log_info.reserved2 = log_info->reserved2; |
| resp->log_info.time_low = htole32(log_info->time_low); |
| resp->log_info.time_high = htole32(log_info->time_high); |
| resp->log_info.entry_prefix_and_length = |
| htole32(log_info->entry_prefix_and_length); |
| resp->log_info.entry_suffix = htole64(log_info->entry_suffix); |
| |
| if (cc == NSM_SUCCESS) { |
| { |
| if (log_data == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| } |
| memcpy(resp->log_data, log_data, log_data_size); |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_get_network_device_log_info_resp( |
| const struct nsm_msg *msg, size_t msg_len, uint8_t *cc, |
| uint16_t *reason_code, uint32_t *next_handle, |
| struct nsm_device_log_info_breakdown *log_info, uint8_t *log_data, |
| uint16_t *log_data_size) |
| { |
| if (log_info == NULL || log_data == NULL || log_data_size == NULL || |
| next_handle == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code); |
| if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) { |
| return rc; |
| } |
| |
| if (msg_len < sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_get_network_device_log_info_resp) - |
| sizeof(uint8_t)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_get_network_device_log_info_resp *resp = |
| (struct nsm_get_network_device_log_info_resp *)msg->payload; |
| |
| uint16_t total_data_size = le16toh(resp->hdr.data_size); |
| *next_handle = le32toh(resp->next_record_handle); |
| *log_data_size = total_data_size - sizeof(resp->next_record_handle) - |
| sizeof(struct nsm_device_log_info); |
| |
| struct nsm_device_log_info info = {0}; |
| info.lost_events_and_synced_time = |
| resp->log_info.lost_events_and_synced_time; |
| info.reserved1 = 0; |
| info.reserved2 = 0; |
| info.time_low = le32toh(resp->log_info.time_low); |
| info.time_high = le32toh(resp->log_info.time_high); |
| info.entry_prefix_and_length = |
| le32toh(resp->log_info.entry_prefix_and_length); |
| info.entry_suffix = le64toh(resp->log_info.entry_suffix); |
| memcpy(log_info, &info, sizeof(struct nsm_device_log_info)); |
| |
| memcpy(log_data, resp->log_data, *log_data_size); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_erase_debug_info_req(uint8_t instance_id, uint8_t info_type, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_REQUEST; |
| header.instance_id = instance_id; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_erase_debug_info_req *request = |
| (struct nsm_erase_debug_info_req *)msg->payload; |
| |
| request->hdr.command = NSM_ERASE_DEBUG_INFO; |
| request->hdr.data_size = sizeof(struct nsm_erase_debug_info_req) - |
| sizeof(struct nsm_common_req); |
| request->debug_info_type = info_type; |
| request->reserved = 0; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_erase_debug_info_req(const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *info_type) |
| { |
| if (msg == NULL || info_type == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (msg_len < sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_erase_debug_info_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_erase_debug_info_req *request = |
| (struct nsm_erase_debug_info_req *)msg->payload; |
| |
| if (request->hdr.data_size != sizeof(struct nsm_erase_debug_info_req) - |
| sizeof(struct nsm_common_req)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *info_type = request->debug_info_type; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_erase_debug_info_resp(uint8_t instance_id, uint8_t cc, |
| uint16_t reason_code, uint8_t result_status, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_RESPONSE; |
| header.instance_id = instance_id & INSTANCEID_MASK; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &msg->hdr); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| if (cc != NSM_SUCCESS) { |
| return encode_reason_code(cc, reason_code, NSM_ERASE_TRACE, |
| msg); |
| } |
| |
| struct nsm_erase_debug_info_resp *response = |
| (struct nsm_erase_debug_info_resp *)msg->payload; |
| |
| response->hdr.command = NSM_ERASE_DEBUG_INFO; |
| response->hdr.completion_code = cc; |
| response->hdr.data_size = |
| htole16(sizeof(struct nsm_erase_debug_info_resp) - |
| sizeof(struct nsm_common_resp)); |
| response->result_status = result_status; |
| response->reserved = 0; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_erase_debug_info_resp(const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *cc, uint16_t *reason_code, |
| uint8_t *result_status) |
| { |
| if (result_status == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code); |
| if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) { |
| return rc; |
| } |
| |
| if (msg_len != sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_erase_debug_info_resp)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_erase_debug_info_resp *response = |
| (struct nsm_erase_debug_info_resp *)msg->payload; |
| |
| uint16_t data_size = le16toh(response->hdr.data_size); |
| if (data_size != sizeof(struct nsm_erase_debug_info_resp) - |
| sizeof(struct nsm_common_resp)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *result_status = response->result_status; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_get_device_debug_parameters_req( |
| uint8_t instance_id, uint8_t debug_configuration_type, |
| struct nsm_debug_parameter_id parameter_id, |
| nsm_debug_parameter_sub_id_bitfield parameter_sub_id, struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| uint8_t rc = encode_common_req_v2(instance_id, NSM_TYPE_DIAGNOSTIC, |
| NSM_GET_DEVICE_DEBUG_PARAMETERS, msg); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| struct nsm_get_device_debug_parameters_req *request = |
| (struct nsm_get_device_debug_parameters_req *)msg->payload; |
| request->hdr.data_size = |
| sizeof(struct nsm_get_device_debug_parameters_req) - |
| sizeof(struct nsm_common_req_v2); |
| request->debug_configuration_type = debug_configuration_type; |
| request->reserved[0] = 0; |
| request->reserved[1] = 0; |
| request->reserved[2] = 0; |
| request->parameter_id.reserved = 0; |
| request->parameter_id.port_number = htole16(parameter_id.port_number); |
| request->parameter_id.index = parameter_id.index; |
| request->parameter_sub_id.value = htole32(parameter_sub_id.value); |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_get_device_debug_parameters_req( |
| const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *debug_configuration_type, |
| struct nsm_debug_parameter_id *parameter_id, |
| nsm_debug_parameter_sub_id_bitfield *parameter_sub_id) |
| { |
| if (msg == NULL || debug_configuration_type == NULL || |
| parameter_id == NULL || parameter_sub_id == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| int rc = decode_common_req_v2(msg, msg_len); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| const struct nsm_get_device_debug_parameters_req *request = |
| (const struct nsm_get_device_debug_parameters_req *)msg->payload; |
| if (request->reserved[0] != 0 || request->reserved[1] != 0 || |
| request->reserved[2] != 0 || request->parameter_id.reserved != 0) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *debug_configuration_type = request->debug_configuration_type; |
| parameter_id->port_number = le16toh(request->parameter_id.port_number); |
| parameter_id->reserved = request->parameter_id.reserved; |
| parameter_id->index = request->parameter_id.index; |
| parameter_sub_id->value = le32toh(request->parameter_sub_id.value); |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_get_device_debug_parameters_resp(uint8_t instance_id, uint8_t cc, |
| uint16_t reason_code, |
| uint16_t *data_size, uint8_t *data, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL || data == NULL || data_size == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| struct nsm_header_info header = {0}; |
| header.nsm_msg_type = NSM_RESPONSE; |
| header.instance_id = instance_id; |
| header.nvidia_msg_type = NSM_TYPE_DIAGNOSTIC; |
| |
| uint8_t rc = pack_nsm_header(&header, &(msg->hdr)); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| if (cc != NSM_SUCCESS) { |
| return encode_reason_code(cc, reason_code, |
| NSM_GET_DEVICE_DEBUG_PARAMETERS, msg); |
| } |
| |
| struct nsm_get_device_debug_parameters_resp *resp = |
| (struct nsm_get_device_debug_parameters_resp *)msg->payload; |
| resp->hdr.command = NSM_GET_DEVICE_DEBUG_PARAMETERS; |
| resp->hdr.completion_code = cc; |
| resp->hdr.data_size = htole16(*data_size); |
| memcpy(resp->data, data, *data_size); |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_get_device_debug_parameters_resp(const struct nsm_msg *msg, |
| size_t msg_len, uint8_t *cc, |
| uint16_t *data_size, uint8_t *data) |
| { |
| if (msg == NULL || cc == NULL || data_size == NULL || data == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (msg_len < sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_get_device_debug_parameters_resp) - |
| 1) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| const struct nsm_get_device_debug_parameters_resp *resp = |
| (const struct nsm_get_device_debug_parameters_resp *)msg->payload; |
| |
| *cc = resp->hdr.completion_code; |
| *data_size = le16toh(resp->hdr.data_size); |
| |
| // Validate data_size against available message buffer |
| size_t available_data_size = msg_len - sizeof(struct nsm_msg_hdr) - |
| sizeof(struct nsm_common_resp); |
| if (*data_size > available_data_size) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| memcpy(data, resp->data, *data_size); |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_set_device_debug_parameters_req( |
| uint8_t instance_id, uint8_t debug_configuration_type, |
| struct nsm_debug_parameter_id parameter_id, |
| nsm_debug_parameter_sub_id_bitfield parameter_sub_id, uint8_t data_size, |
| uint8_t *data, struct nsm_msg *msg) |
| { |
| if (msg == NULL || data == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| uint8_t rc = encode_common_req_v2(instance_id, NSM_TYPE_DIAGNOSTIC, |
| NSM_SET_DEVICE_DEBUG_PARAMETERS, msg); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_set_device_debug_parameters_req *request = |
| (struct nsm_set_device_debug_parameters_req *)msg->payload; |
| request->hdr.data_size = |
| sizeof(struct nsm_set_device_debug_parameters_req) - |
| sizeof(struct nsm_common_req_v2) + data_size - sizeof(uint8_t); |
| request->debug_configuration_type = debug_configuration_type; |
| request->data_size = data_size; |
| request->reserved[0] = 0; |
| request->reserved[1] = 0; |
| request->parameter_id.reserved = 0; |
| request->parameter_id.port_number = htole16(parameter_id.port_number); |
| request->parameter_id.index = parameter_id.index; |
| request->parameter_sub_id.value = htole32(parameter_sub_id.value); |
| memcpy(request->data, data, data_size); |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_set_device_debug_parameters_req( |
| const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *debug_configuration_type, |
| struct nsm_debug_parameter_id *parameter_id, |
| nsm_debug_parameter_sub_id_bitfield *parameter_sub_id, uint8_t *data_size, |
| uint8_t **data) |
| { |
| if (msg == NULL || debug_configuration_type == NULL || |
| parameter_id == NULL || parameter_sub_id == NULL || |
| data_size == NULL || data == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| int rc = decode_common_req_v2(msg, msg_len); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| const struct nsm_set_device_debug_parameters_req *request = |
| (const struct nsm_set_device_debug_parameters_req *)msg->payload; |
| |
| if (request->reserved[0] != 0 || request->reserved[1] != 0 || |
| request->parameter_id.reserved != 0) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| *debug_configuration_type = request->debug_configuration_type; |
| parameter_id->port_number = le16toh(request->parameter_id.port_number); |
| parameter_id->reserved = request->parameter_id.reserved; |
| parameter_id->index = request->parameter_id.index; |
| parameter_sub_id->value = le32toh(request->parameter_sub_id.value); |
| *data_size = request->data_size; |
| memcpy(data, request->data, *data_size); |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_set_device_debug_parameters_resp(const struct nsm_msg *msg, |
| size_t msg_len, uint8_t *cc) |
| { |
| if (msg == NULL || cc == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| |
| if (msg_len < |
| sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| const struct nsm_common_resp *resp = |
| (const struct nsm_common_resp *)msg->payload; |
| *cc = resp->completion_code; |
| return NSM_SW_SUCCESS; |
| } |