blob: b9a515c793974a7525b19b3e8523f5d0e8bc0f4f [file] [log] [blame] [edit]
/*
* 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;
}