| /* |
| * 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 "debug-token.h" |
| |
| #include <endian.h> |
| #include <string.h> |
| |
| int decode_nsm_query_token_parameters_req( |
| const struct nsm_msg *msg, size_t msg_len, |
| enum nsm_debug_token_opcode *token_opcode) |
| { |
| if (msg == NULL || token_opcode == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| if (msg_len < sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_query_token_parameters_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_query_token_parameters_req *request = |
| (struct nsm_query_token_parameters_req *)msg->payload; |
| if (request->hdr.data_size < sizeof(request->token_opcode)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| *token_opcode = request->token_opcode; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_query_token_parameters_req( |
| uint8_t instance_id, enum nsm_debug_token_opcode token_opcode, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| if (token_opcode != NSM_DEBUG_TOKEN_OPCODE_RMCS && |
| token_opcode != NSM_DEBUG_TOKEN_OPCODE_RMDT && |
| token_opcode != NSM_DEBUG_TOKEN_OPCODE_CRCS && |
| token_opcode != NSM_DEBUG_TOKEN_OPCODE_CRDT && |
| token_opcode != NSM_DEBUG_TOKEN_OPCODE_LINKX_FRC) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| 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_query_token_parameters_req *request = |
| (struct nsm_query_token_parameters_req *)msg->payload; |
| request->hdr.command = NSM_QUERY_TOKEN_PARAMETERS; |
| request->hdr.data_size = 1; |
| request->token_opcode = token_opcode; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_nsm_query_token_parameters_resp( |
| const struct nsm_msg *msg, size_t msg_len, uint8_t *cc, |
| uint16_t *reason_code, struct nsm_debug_token_request *token_request) |
| { |
| if (msg == NULL || token_request == 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_query_token_parameters_resp)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_query_token_parameters_resp *resp = |
| (struct nsm_query_token_parameters_resp *)msg->payload; |
| if (resp->token_request.token_request_size != |
| sizeof(struct nsm_debug_token_request)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| *token_request = resp->token_request; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_query_token_parameters_resp( |
| uint8_t instance_id, uint8_t cc, uint16_t reason_code, |
| struct nsm_debug_token_request *token_request, 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; |
| 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_QUERY_TOKEN_PARAMETERS, msg); |
| } |
| |
| struct nsm_query_token_parameters_resp *response = |
| (struct nsm_query_token_parameters_resp *)msg->payload; |
| response->hdr.command = NSM_QUERY_TOKEN_PARAMETERS; |
| response->hdr.completion_code = cc; |
| response->hdr.data_size = |
| htole16(sizeof(struct nsm_debug_token_request)); |
| response->token_request = *token_request; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_nsm_provide_token_req(const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *token_data, uint8_t *token_data_len) |
| { |
| if (msg == NULL || token_data == NULL || token_data_len == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| if (msg_len < |
| sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_provide_token_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_provide_token_req *request = |
| (struct nsm_provide_token_req *)msg->payload; |
| if (request->hdr.data_size == 0) { |
| return NSM_SW_ERROR_DATA; |
| } |
| memcpy(token_data, request->token_data, request->hdr.data_size); |
| *token_data_len = request->hdr.data_size; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_provide_token_req(uint8_t instance_id, const uint8_t *token_data, |
| const uint16_t token_data_len, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL || token_data == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| if (token_data_len == 0) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| 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_v2(&header, &msg->hdr); |
| if (rc != NSM_SW_SUCCESS) { |
| return rc; |
| } |
| |
| struct nsm_provide_token_req *request = |
| (struct nsm_provide_token_req *)msg->payload; |
| request->hdr.command = NSM_PROVIDE_TOKEN; |
| request->hdr.data_size = htole16(token_data_len); |
| memcpy(request->token_data, token_data, token_data_len); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_nsm_provide_token_resp(const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *cc, uint16_t *reason_code) |
| { |
| if (msg == NULL || cc == NULL || reason_code == 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(nsm_provide_token_resp)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_provide_token_resp(uint8_t instance_id, uint8_t cc, |
| uint16_t reason_code, 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; |
| 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_PROVIDE_TOKEN, |
| msg); |
| } |
| |
| struct nsm_query_token_parameters_resp *response = |
| (struct nsm_query_token_parameters_resp *)msg->payload; |
| response->hdr.command = NSM_PROVIDE_TOKEN; |
| response->hdr.completion_code = cc; |
| response->hdr.data_size = 0; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_nsm_disable_tokens_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(nsm_disable_tokens_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_disable_tokens_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; |
| } |
| |
| nsm_disable_tokens_req *request = |
| (nsm_disable_tokens_req *)msg->payload; |
| request->command = NSM_DISABLE_TOKENS; |
| request->data_size = 0; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_nsm_disable_tokens_resp(const struct nsm_msg *msg, size_t msg_len, |
| uint8_t *cc, uint16_t *reason_code) |
| { |
| if (msg == NULL || cc == NULL || reason_code == 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(nsm_disable_tokens_resp)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_disable_tokens_resp(uint8_t instance_id, uint8_t cc, |
| uint16_t reason_code, 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; |
| 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_DISABLE_TOKENS, |
| msg); |
| } |
| |
| struct nsm_query_token_parameters_resp *response = |
| (struct nsm_query_token_parameters_resp *)msg->payload; |
| response->hdr.command = NSM_DISABLE_TOKENS; |
| response->hdr.completion_code = cc; |
| response->hdr.data_size = 0; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_nsm_query_token_status_req(const struct nsm_msg *msg, size_t msg_len, |
| enum nsm_debug_token_type *token_type) |
| { |
| if (msg == NULL || token_type == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| if (msg_len < sizeof(struct nsm_msg_hdr) + |
| sizeof(struct nsm_query_token_status_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_query_token_status_req *request = |
| (struct nsm_query_token_status_req *)msg->payload; |
| if (request->hdr.data_size < sizeof(request->token_type)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| *token_type = request->token_type; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_query_token_status_req(uint8_t instance_id, |
| enum nsm_debug_token_type token_type, |
| struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_NULL; |
| } |
| if (token_type != NSM_DEBUG_TOKEN_TYPE_FRC && |
| token_type != NSM_DEBUG_TOKEN_TYPE_CRCS && |
| token_type != NSM_DEBUG_TOKEN_TYPE_CRDT && |
| token_type != NSM_DEBUG_TOKEN_TYPE_DEBUG_FIRMWARE) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| 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_query_token_status_req *request = |
| (struct nsm_query_token_status_req *)msg->payload; |
| request->hdr.command = NSM_QUERY_TOKEN_STATUS; |
| request->hdr.data_size = 1; |
| request->token_type = token_type; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_nsm_query_token_status_resp( |
| const struct nsm_msg *msg, size_t msg_len, uint8_t *cc, |
| uint16_t *reason_code, enum nsm_debug_token_status *status, |
| enum nsm_debug_token_status_additional_info *additional_info, |
| enum nsm_debug_token_type *token_type, uint32_t *time_left) |
| { |
| if (msg == NULL || status == NULL || additional_info == NULL || |
| token_type == NULL || time_left == 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_query_token_status_resp)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| struct nsm_query_token_status_resp *resp = |
| (struct nsm_query_token_status_resp *)msg->payload; |
| *status = resp->status; |
| *additional_info = resp->additional_info; |
| *token_type = resp->token_type; |
| *time_left = resp->time_left; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_query_token_status_resp( |
| uint8_t instance_id, uint8_t cc, uint16_t reason_code, |
| enum nsm_debug_token_status status, |
| enum nsm_debug_token_status_additional_info additional_info, |
| enum nsm_debug_token_type token_type, uint32_t time_left, |
| 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; |
| 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_QUERY_TOKEN_STATUS, msg); |
| } |
| |
| struct nsm_query_token_status_resp *response = |
| (struct nsm_query_token_status_resp *)msg->payload; |
| response->hdr.command = NSM_QUERY_TOKEN_STATUS; |
| response->hdr.completion_code = cc; |
| response->hdr.data_size = |
| htole16(sizeof(status) + sizeof(additional_info) + |
| sizeof(token_type) + sizeof(time_left)); |
| response->status = status; |
| response->additional_info = additional_info; |
| response->token_type = token_type; |
| response->time_left = time_left; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_nsm_query_device_ids_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(nsm_query_device_ids_req)) { |
| return NSM_SW_ERROR_LENGTH; |
| } |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_query_device_ids_req(uint8_t instance_id, struct nsm_msg *msg) |
| { |
| if (msg == NULL) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| 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; |
| } |
| |
| nsm_query_device_ids_req *request = |
| (nsm_query_device_ids_req *)msg->payload; |
| request->command = NSM_QUERY_DEVICE_IDS; |
| request->data_size = 0; |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int decode_nsm_query_device_ids_resp( |
| const struct nsm_msg *msg, size_t msg_len, uint8_t *cc, |
| uint16_t *reason_code, uint8_t device_id[NSM_DEBUG_TOKEN_DEVICE_ID_SIZE]) |
| { |
| if (msg == NULL || cc == NULL || reason_code == 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_query_device_ids_resp)) { |
| return NSM_SW_ERROR_DATA; |
| } |
| |
| struct nsm_query_device_ids_resp *resp = |
| (struct nsm_query_device_ids_resp *)msg->payload; |
| memcpy(device_id, resp->device_id, NSM_DEBUG_TOKEN_DEVICE_ID_SIZE); |
| |
| return NSM_SW_SUCCESS; |
| } |
| |
| int encode_nsm_query_device_ids_resp( |
| uint8_t instance_id, uint8_t cc, uint16_t reason_code, |
| const uint8_t device_id[NSM_DEBUG_TOKEN_DEVICE_ID_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; |
| 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_QUERY_DEVICE_IDS, |
| msg); |
| } |
| |
| struct nsm_query_device_ids_resp *response = |
| (struct nsm_query_device_ids_resp *)msg->payload; |
| response->hdr.command = NSM_QUERY_DEVICE_IDS; |
| response->hdr.completion_code = cc; |
| response->hdr.data_size = htole16(NSM_DEBUG_TOKEN_DEVICE_ID_SIZE); |
| memcpy(response->device_id, device_id, NSM_DEBUG_TOKEN_DEVICE_ID_SIZE); |
| |
| return NSM_SW_SUCCESS; |
| } |