blob: cd2af6b1373a83a9f55d7180cd885eb870f1e01a [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 "firmware-utils.h"
#include <endian.h>
#include <stdio.h>
#include <string.h>
#define DBG1(x)
#define DBG2(x)
#define DBGW(x)
#define DBGE(x) x
void printArrayAsHex(const uint8_t *array, size_t size)
{
for (size_t i = 0; i < size; ++i) {
printf("%02X ", array[i]);
}
printf("\n");
}
void encode_nsm_firmware_aggregate_tag_uint8(uint8_t **buffer, uint8_t tag,
uint8_t value,
uint16_t *buffer_size)
{
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
field->tag = tag;
field->valid = 1;
field->length = 0;
field->reserved = 0;
field->data[0] = value;
*buffer +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1;
*buffer_size +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1;
}
void encode_nsm_firmware_aggregate_tag_uint16(uint8_t **buffer, uint8_t tag,
uint16_t value,
uint16_t *buffer_size)
{
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
field->tag = tag;
field->valid = 1;
field->length = 1;
field->reserved = 0;
value = htole16(value);
memcpy(field->data, &value, sizeof(uint16_t));
*buffer +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1;
*buffer_size +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1;
}
void encode_nsm_firmware_aggregate_tag_uint32(uint8_t **buffer, uint8_t tag,
uint32_t value,
uint16_t *buffer_size)
{
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
field->tag = tag;
field->valid = 1;
field->length = 2;
field->reserved = 0;
value = htole32(value);
memcpy(field->data, &value, sizeof(uint32_t));
*buffer +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1;
*buffer_size +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1;
}
void encode_nsm_firmware_aggregate_tag_uint64(uint8_t **buffer, uint8_t tag,
uint64_t value,
uint16_t *buffer_size)
{
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
field->tag = tag;
field->valid = 1;
field->length = 3;
field->reserved = 0;
value = htole64(value);
memcpy(field->data, &value, sizeof(uint64_t));
*buffer +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1;
*buffer_size +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1;
}
void encode_nsm_firmware_aggregate_tag_uint8_array(uint8_t **buffer,
uint8_t tag, uint8_t *value,
uint16_t *buffer_size)
{
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
field->tag = tag;
field->valid = 1;
field->length = 4;
field->reserved = 0;
memcpy(field->data, value, 16);
*buffer += sizeof(struct nsm_firmware_aggregate_tag) + 16 - 1;
*buffer_size += sizeof(struct nsm_firmware_aggregate_tag) + 16 - 1;
}
bool decode_nsm_firmware_aggregate_tag_uint8(uint8_t **buffer, uint8_t *tag,
uint8_t *valid, uint8_t *value,
uint16_t *buffer_size)
{
if (*buffer_size <
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1) {
return false;
}
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
*tag = field->tag;
*valid = field->valid;
if (field->valid) {
*value = field->data[0];
}
*buffer +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1;
*buffer_size -=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1;
return true;
}
bool decode_nsm_firmware_aggregate_tag_uint16(uint8_t **buffer, uint8_t *tag,
uint8_t *valid, uint16_t *value,
uint16_t *buffer_size)
{
if (*buffer_size <
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1) {
return false;
}
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
*tag = field->tag;
*valid = field->valid;
if (field->valid) {
memcpy(value, field->data, sizeof(uint16_t));
*value = le16toh(*value);
}
*buffer +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1;
*buffer_size -=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1;
return true;
}
bool decode_nsm_firmware_aggregate_tag_uint32(uint8_t **buffer, uint8_t *tag,
uint8_t *valid, uint32_t *value,
uint16_t *buffer_size)
{
if (*buffer_size <
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1) {
return false;
}
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
*tag = field->tag;
*valid = field->valid;
if (field->valid) {
memcpy(value, field->data, sizeof(uint32_t));
*value = le32toh(*value);
}
*buffer +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1;
*buffer_size -=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1;
return true;
}
bool decode_nsm_firmware_aggregate_tag_uint64(uint8_t **buffer, uint8_t *tag,
uint8_t *valid, uint64_t *value,
uint16_t *buffer_size)
{
if (*buffer_size <
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1) {
return false;
}
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
*tag = field->tag;
*valid = field->valid;
if (field->valid) {
memcpy(value, field->data, sizeof(uint64_t));
*value = le64toh(*value);
}
*buffer +=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1;
*buffer_size -=
sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1;
return true;
}
bool decode_nsm_firmware_aggregate_tag_uint8_array(uint8_t **buffer,
uint8_t *tag, uint8_t *valid,
uint8_t *value,
uint16_t *buffer_size)
{
uint16_t length;
if (*buffer_size < sizeof(struct nsm_firmware_aggregate_tag) + 4 - 1) {
return false;
}
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
*tag = field->tag;
*valid = field->valid;
length = 1 << field->length;
if (*buffer_size <
sizeof(struct nsm_firmware_aggregate_tag) + length - 1) {
return false;
}
if (field->valid) {
memcpy(value, field->data, length);
}
*buffer += sizeof(struct nsm_firmware_aggregate_tag) + length - 1;
*buffer_size -= sizeof(struct nsm_firmware_aggregate_tag) + length - 1;
return true;
}
/**
* Skip the tag data by advancing the pointer
* @param buffer: pointer to the buffer
* @param buffer_size: size of the buffer
* @return true if the tag is skipped, false otherwise
*/
bool decode_nsm_firmware_aggregate_tag_skip(uint8_t **buffer,
uint16_t *buffer_size)
{
if (*buffer_size < sizeof(struct nsm_firmware_aggregate_tag)) {
return false;
}
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*buffer;
size_t data_len = 1 << field->length;
size_t consumed_len =
sizeof(struct nsm_firmware_aggregate_tag) + data_len - 1;
if (*buffer_size < consumed_len) {
return false;
}
*buffer += consumed_len;
*buffer_size -= consumed_len;
return true;
}
int decode_nsm_query_get_erot_state_parameters_req(
const struct nsm_msg *msg, size_t msg_len,
struct nsm_firmware_erot_state_info_req *fw_req)
{
if (msg == NULL || fw_req == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_firmware_get_erot_state_info_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_get_erot_state_info_req *request =
(struct nsm_firmware_get_erot_state_info_req *)msg->payload;
if (request->hdr.data_size < sizeof(*fw_req)) {
return NSM_SW_ERROR_DATA;
}
*fw_req = request->fq_req;
return NSM_SW_SUCCESS;
}
int encode_nsm_query_get_erot_state_parameters_req(
uint8_t instance_id, const struct nsm_firmware_erot_state_info_req *fw_req,
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_FIRMWARE;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_firmware_get_erot_state_info_req *request =
(struct nsm_firmware_get_erot_state_info_req *)msg->payload;
request->hdr.command = NSM_FW_GET_EROT_STATE_INFORMATION;
request->hdr.data_size =
htole16(sizeof(struct nsm_firmware_erot_state_info_req));
memcpy(&request->fq_req, fw_req,
sizeof(struct nsm_firmware_erot_state_info_req));
return NSM_SW_SUCCESS;
}
int encode_nsm_query_get_erot_state_parameters_resp(
uint8_t instance_id, uint8_t cc, uint16_t reason_code,
struct nsm_firmware_erot_state_info_resp *fw_info, 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_FIRMWARE;
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_FW_GET_EROT_STATE_INFORMATION, msg);
}
struct nsm_firmware_get_erot_state_info_resp *response =
(struct nsm_firmware_get_erot_state_info_resp *)msg->payload;
response->hdr.command = NSM_FW_GET_EROT_STATE_INFORMATION;
response->hdr.completion_code = cc;
uint16_t telemetry_count = 0;
uint16_t msg_size = sizeof(struct nsm_common_telemetry_resp);
uint8_t *ptr = &(response->payload[0]);
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_BACKGROUND_COPY_POLICY_PERSISTENT,
fw_info->fq_resp_hdr.background_copy_policy, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_ACTIVE_FIRMWARE_SLOT,
fw_info->fq_resp_hdr.active_slot, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_ACTIVE_KEY_SET,
fw_info->fq_resp_hdr.active_keyset, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint16(
&ptr, NSM_FIRMWARE_MINIMUM_SECURITY_VERSION_NUMBER,
fw_info->fq_resp_hdr.minimum_security_version, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_INBAND_UPDATE_POLICY_PERSISTENT,
fw_info->fq_resp_hdr.inband_update_policy, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint64(
&ptr, NSM_FIRMWARE_BOOT_STATUS_CODE,
fw_info->fq_resp_hdr.boot_status_code, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_FIRMWARE_SLOT_COUNT,
fw_info->fq_resp_hdr.firmware_slot_count, &msg_size);
telemetry_count++;
for (int i = 0; i < fw_info->fq_resp_hdr.firmware_slot_count; i++) {
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_FIRMWARE_SLOT_ID,
fw_info->slot_info[i].slot_id, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint8_array(
&ptr, NSM_FIRMWARE_FIRMWARE_VERSION_STRING,
(uint8_t *)(&(
fw_info->slot_info[i].firmware_version_string[0])),
&msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint32(
&ptr, NSM_FIRMWARE_VERSION_COMPARISON_STAMP,
fw_info->slot_info[i].version_comparison_stamp, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_BUILD_TYPE,
fw_info->slot_info[i].build_type, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_SIGNING_TYPE,
fw_info->slot_info[i].signing_type, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_WRITE_PROTECT_STATE,
fw_info->slot_info[i].write_protect_state, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint8(
&ptr, NSM_FIRMWARE_FIRMWARE_STATE,
fw_info->slot_info[i].firmware_state, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint16(
&ptr, NSM_FIRMWARE_SECURITY_VERSION_NUMBER,
fw_info->slot_info[i].security_version_number, &msg_size);
telemetry_count++;
encode_nsm_firmware_aggregate_tag_uint16(
&ptr, NSM_FIRMWARE_SIGNING_KEY_INDEX,
fw_info->slot_info[i].signing_key_index, &msg_size);
telemetry_count++;
}
response->hdr.telemetry_count = htole16(telemetry_count);
DBG1(printf("Telemetry count = %u, resp buffer (size = %u):\n",
(uint32_t)telemetry_count, (uint32_t)msg_size);)
DBG1(printArrayAsHex(&(response->payload[0]), msg_size);)
return NSM_SW_SUCCESS;
}
int decode_nsm_query_firmware_header_information(
struct nsm_firmware_erot_state_info_hdr_resp *fw_info_hdr, uint8_t **ptr,
uint16_t *payload_size, uint16_t *telemetry_count)
{
uint8_t tag, valid;
bool rc_ok;
while ((*payload_size >= sizeof(struct nsm_firmware_aggregate_tag)) &&
(*telemetry_count > 0)) {
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*ptr;
tag = field->tag;
if (tag == NSM_FIRMWARE_BACKGROUND_COPY_POLICY_PERSISTENT) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid,
&(fw_info_hdr->background_copy_policy),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf(
"Decoded "
"NSM_FIRMWARE_BACKGROUND_COPY_POLICY_"
"PERSISTENT, "
"value = 0x%02x\n",
fw_info_hdr->background_copy_policy);)
}
} else if (tag == NSM_FIRMWARE_ACTIVE_FIRMWARE_SLOT) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid, &(fw_info_hdr->active_slot),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf("Decoded "
"NSM_FIRMWARE_ACTIVE_FIRMWARE_SLOT,"
" value = 0x%02x\n",
fw_info_hdr->active_slot);)
}
} else if (tag == NSM_FIRMWARE_ACTIVE_KEY_SET) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid, &(fw_info_hdr->active_keyset),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf(
"Decoded NSM_FIRMWARE_ACTIVE_KEY_SET, "
"value = 0x%02x\n",
fw_info_hdr->active_keyset);)
}
} else if (tag ==
NSM_FIRMWARE_MINIMUM_SECURITY_VERSION_NUMBER) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint16(
ptr, &tag, &valid,
&(fw_info_hdr->minimum_security_version),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(
printf(
"Decoded "
"NSM_FIRMWARE_MINIMUM_SECURITY_VERSION_"
"NUMBER, value = 0x%04x\n",
fw_info_hdr->minimum_security_version);)
}
} else if (tag ==
NSM_FIRMWARE_INBAND_UPDATE_POLICY_PERSISTENT) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid,
&(fw_info_hdr->inband_update_policy), payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf("Decoded "
"NSM_FIRMWARE_INBAND_UPDATE_POLICY_"
"PERSISTENT,"
" value = 0x%02x\n",
fw_info_hdr->inband_update_policy);)
}
} else if (tag == NSM_FIRMWARE_BOOT_STATUS_CODE) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint64(
ptr, &tag, &valid, &(fw_info_hdr->boot_status_code),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf("Decoded "
"NSM_FIRMWARE_BOOT_STATUS_CODE,"
" value = 0x%016lx\n",
fw_info_hdr->boot_status_code);)
}
} else if (tag == NSM_FIRMWARE_FIRMWARE_SLOT_COUNT) {
if (decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid,
&(fw_info_hdr->firmware_slot_count),
payload_size)) {
(*telemetry_count)--;
DBG2(printf("Decoded "
"NSM_FIRMWARE_FIRMWARE_SLOT_COUNT, "
"value = 0x%02x\n",
fw_info_hdr->firmware_slot_count);)
break;
}
rc_ok = false;
} else if (tag == NSM_FIRMWARE_INBAND_UPDATE_POLICY_CURRENT) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid,
&(fw_info_hdr->inband_update_policy_current),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(
printf("Decoded "
"NSM_FIRMWARE_INBAND_UPDATE_POLICY_"
"CURRENT, "
"value = 0x%02x\n",
fw_info_hdr
->inband_update_policy_current);)
}
} else if (tag == NSM_FIRMWARE_BACKGROUND_COPY_POLICY_CURRENT) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid,
&(fw_info_hdr->background_copy_policy_current),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf(
"Decoded "
"NSM_FIRMWARE_BACKGROUND_COPY_POLICY_"
"CURRENT, "
"value = 0x%02x\n",
fw_info_hdr
->background_copy_policy_current);)
}
} else if (tag == NSM_FIRMWARE_AP_SKU_ID) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint32(
ptr, &tag, &valid, &(fw_info_hdr->ap_sku_id),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf("Decoded "
"NSM_FIRMWARE_AP_SKU_ID, "
"CURRENT, "
"value = 0x%08x\n",
fw_info_hdr->ap_sku_id);)
}
} else {
/* Skip unsupported tag */
DBG2(printf(
"Skipping unsupported tag in header: 0x%02x\n",
field->tag);)
DBG2(printf("Left telemetries: %u, left payload: %u\n",
(uint32_t)(*telemetry_count),
(uint32_t)(*payload_size));)(
*telemetry_count)--;
rc_ok = decode_nsm_firmware_aggregate_tag_skip(
ptr, payload_size);
if (!rc_ok) {
DBGE(printf("Error: The decoded message header "
"is not "
"properly encoded\n");)
DBGE(printf("Left telemetries: %u, left "
"payload: %u\n",
(uint32_t)(*telemetry_count),
(uint32_t)(*payload_size));)
return NSM_SW_ERROR_LENGTH;
}
}
if (!rc_ok) {
DBGE(printf("Error: The decoded message header is not "
"properly encoded\n");)
DBGE(printf("Left telemetries: %u, left payload: %u\n",
(uint32_t)(*telemetry_count),
(uint32_t)(*payload_size));)
return NSM_SW_ERROR_LENGTH;
}
}
DBG2(printf("Success in decoding the response header\n");)
return NSM_SW_SUCCESS;
}
int decode_nsm_query_firmware_slot_information(
struct nsm_firmware_slot_info *fw_slot_info, uint8_t **ptr,
uint16_t *payload_size, uint16_t *telemetry_count)
{
uint8_t tag, valid;
bool rc_ok;
if ((*payload_size < sizeof(struct nsm_firmware_aggregate_tag)) ||
(*telemetry_count == 0)) {
DBG2(printf("Error: Expected NSM_FIRMWARE_FIRMWARE_SLOT_ID, "
"but there is no more tags in the message\n");)
return NSM_SW_ERROR_DATA;
}
struct nsm_firmware_aggregate_tag *field =
(struct nsm_firmware_aggregate_tag *)*ptr;
tag = field->tag;
// Firmware slot ID tag must be always as the first one
if (tag == NSM_FIRMWARE_FIRMWARE_SLOT_ID) {
if (!decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid, &(fw_slot_info->slot_id),
payload_size)) {
return NSM_SW_ERROR_LENGTH;
}
(*telemetry_count)--;
DBG2(printf(
"Decoded NSM_FIRMWARE_FIRMWARE_SLOT_ID, value = %u\n",
fw_slot_info->slot_id);)
} else {
return NSM_SW_ERROR_DATA;
}
while ((*payload_size >= sizeof(struct nsm_firmware_aggregate_tag)) &&
(*telemetry_count > 0)) {
field = (struct nsm_firmware_aggregate_tag *)*ptr;
tag = field->tag;
if (tag == NSM_FIRMWARE_FIRMWARE_VERSION_STRING) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8_array(
ptr, &tag, &valid,
(uint8_t *)(&(
fw_slot_info->firmware_version_string[0])),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(
printf(
"Decoded "
"NSM_FIRMWARE_FIRMWARE_VERSION_STRING, "
"value = %s\n",
(char
*)(fw_slot_info
->firmware_version_string));)
}
} else if (tag == NSM_FIRMWARE_VERSION_COMPARISON_STAMP) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint32(
ptr, &tag, &valid,
&(fw_slot_info->version_comparison_stamp),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf("Decoded "
"NSM_FIRMWARE_VERSION_COMPARISON_"
"STAMP, value = %u\n",
fw_slot_info
->version_comparison_stamp);)
}
} else if (tag == NSM_FIRMWARE_BUILD_TYPE) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid, &(fw_slot_info->build_type),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf("Decoded NSM_FIRMWARE_BUILD_TYPE, "
"value = %u\n",
fw_slot_info->build_type);)
}
} else if (tag == NSM_FIRMWARE_SIGNING_TYPE) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid, &(fw_slot_info->signing_type),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(
printf("Decoded NSM_FIRMWARE_SIGNING_TYPE, "
"value = %u\n",
fw_slot_info->signing_type);)
}
} else if (tag == NSM_FIRMWARE_WRITE_PROTECT_STATE) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid,
&(fw_slot_info->write_protect_state), payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf("Decoded "
"NSM_FIRMWARE_WRITE_PROTECT_STATE, "
"value = %u\n",
fw_slot_info->write_protect_state);)
}
} else if (tag == NSM_FIRMWARE_FIRMWARE_STATE) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
ptr, &tag, &valid, &(fw_slot_info->firmware_state),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf(
"Decoded NSM_FIRMWARE_FIRMWARE_STATE, "
"value = %u\n",
fw_slot_info->firmware_state);)
}
} else if (tag == NSM_FIRMWARE_SECURITY_VERSION_NUMBER) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint16(
ptr, &tag, &valid,
&(fw_slot_info->security_version_number),
payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(
printf(
"Decoded "
"NSM_FIRMWARE_SECURITY_VERSION_NUMBER, "
"value = %u\n",
fw_slot_info->security_version_number);)
}
} else if (tag == NSM_FIRMWARE_SIGNING_KEY_INDEX) {
rc_ok = decode_nsm_firmware_aggregate_tag_uint16(
ptr, &tag, &valid,
&(fw_slot_info->signing_key_index), payload_size);
if (rc_ok) {
(*telemetry_count)--;
DBG2(printf("Decoded "
"NSM_FIRMWARE_SIGNING_KEY_INDEX, "
"value = %u\n",
fw_slot_info->signing_key_index);)
}
} else if (tag == NSM_FIRMWARE_FIRMWARE_SLOT_ID) {
/* we are good, we reached new firmware slot id */
return NSM_SW_SUCCESS;
} else {
/* Skip unsupported tag */
DBG2(printf("Skipping unsupported tag in slot "
"information: 0x%02x\n",
field->tag);)
DBG2(printf("Left telemetries: %u, left payload: %u\n",
(uint32_t)(*telemetry_count),
(uint32_t)(*payload_size));)(
*telemetry_count)--;
rc_ok = decode_nsm_firmware_aggregate_tag_skip(
ptr, payload_size);
if (!rc_ok) {
DBGE(printf("Error: The decoded message slot "
"information is not properly "
"encoded\n");)
DBGE(printf("Left telemetries: %u, left "
"payload: %u\n",
(uint32_t)(*telemetry_count),
(uint32_t)(*payload_size));)
return NSM_SW_ERROR_LENGTH;
}
}
if (!rc_ok) {
DBGE(printf("Error: The decoded message slot "
"information is not properly encoded\n");)
DBGE(printf("Left telemetries: %u, left payload: %u\n",
(uint32_t)(*telemetry_count),
(uint32_t)(*payload_size));)
return NSM_SW_ERROR_LENGTH;
}
}
DBG2(printf("Success in decoding the response slot information\n");)
return NSM_SW_SUCCESS;
}
int decode_nsm_query_get_erot_state_parameters_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code, struct nsm_firmware_erot_state_info_resp *fw_resp)
{
if (msg == NULL || fw_resp == NULL) {
return NSM_SW_ERROR_NULL;
}
DBG1(printf("Received Resp buffer (size = %zi):\n", msg_len);)
DBG1(printArrayAsHex(&(msg->payload[0]), msg_len);)
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_firmware_aggregate_tag)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_get_erot_state_info_resp *resp =
(struct nsm_firmware_get_erot_state_info_resp *)msg->payload;
uint8_t *ptr = &(resp->payload[0]);
uint16_t telemetry_count = resp->hdr.telemetry_count;
uint16_t payload_size = (uint16_t)msg_len - sizeof(struct nsm_msg_hdr) -
sizeof(struct nsm_common_telemetry_resp);
DBG2(printf("Telemetry count = %u, msg max size = %u:\n",
(uint32_t)telemetry_count, (uint32_t)payload_size);)
int ret = decode_nsm_query_firmware_header_information(
&(fw_resp->fq_resp_hdr), &ptr, &payload_size, &telemetry_count);
if (ret) {
DBGE(printf("Full payload (len = %zi):\n", msg_len);)
DBGE(printArrayAsHex((const uint8_t *)msg, msg_len);)
return ret;
}
DBG2(printf("Payload remaining size = %u):\n", (uint32_t)payload_size);)
if (fw_resp->fq_resp_hdr.firmware_slot_count > 0) {
int slot_info_len = sizeof(struct nsm_firmware_slot_info) *
fw_resp->fq_resp_hdr.firmware_slot_count;
fw_resp->slot_info = malloc(slot_info_len);
memset((char *)(fw_resp->slot_info), 0, slot_info_len);
for (int i = 0; i < fw_resp->fq_resp_hdr.firmware_slot_count;
i++) {
int ret = decode_nsm_query_firmware_slot_information(
&(fw_resp->slot_info[i]), &ptr, &payload_size,
&telemetry_count);
if (ret) {
DBGE(printf("Full payload (len = %zi):\n",
msg_len);)
DBGE(printArrayAsHex((const uint8_t *)msg,
msg_len);)
return ret;
}
}
} else {
fw_resp->slot_info = NULL;
}
return NSM_SW_SUCCESS;
}
int encode_nsm_firmware_irreversible_config_req(
uint8_t instance_id,
const struct nsm_firmware_irreversible_config_req *fw_req,
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_FIRMWARE;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_firmware_irreversible_config_req_command *request =
(struct nsm_firmware_irreversible_config_req_command *)msg->payload;
request->hdr.command = NSM_FW_IRREVERSABLE_CONFIGURATION;
request->hdr.data_size =
sizeof(struct nsm_firmware_irreversible_config_req);
memcpy(&request->irreversible_cfg_req, fw_req,
sizeof(struct nsm_firmware_irreversible_config_req));
return NSM_SW_SUCCESS;
}
int decode_nsm_firmware_irreversible_config_req(
const struct nsm_msg *msg, size_t msg_len,
struct nsm_firmware_irreversible_config_req *fw_req)
{
if (msg == NULL || fw_req == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_firmware_irreversible_config_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_irreversible_config_req_command *request =
(struct nsm_firmware_irreversible_config_req_command *)msg->payload;
if (request->hdr.data_size < sizeof(*fw_req)) {
return NSM_SW_ERROR_DATA;
}
*fw_req = request->irreversible_cfg_req;
return NSM_SW_SUCCESS;
}
int encode_nsm_firmware_irreversible_config_request_0_resp(
uint8_t instance_id, uint8_t cc, uint16_t reason_code,
struct nsm_firmware_irreversible_config_request_0_resp *cfg_resp,
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_FIRMWARE;
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_FW_IRREVERSABLE_CONFIGURATION, msg);
}
struct nsm_firmware_irreversible_config_request_0_resp_command
*response =
(struct nsm_firmware_irreversible_config_request_0_resp_command
*)msg->payload;
response->hdr.command = NSM_FW_IRREVERSABLE_CONFIGURATION;
response->hdr.completion_code = cc;
uint16_t msg_size =
sizeof(struct nsm_common_resp) +
sizeof(struct nsm_firmware_irreversible_config_request_0_resp);
response->hdr.data_size = htole16(msg_size);
memcpy(&(response->irreversible_cfg_query), cfg_resp,
sizeof(struct nsm_firmware_irreversible_config_request_0_resp));
return NSM_SW_SUCCESS;
}
int encode_nsm_firmware_irreversible_config_request_1_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_FIRMWARE;
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_FW_IRREVERSABLE_CONFIGURATION, msg);
}
struct nsm_firmware_irreversible_config_request_1_resp_command
*response =
(struct nsm_firmware_irreversible_config_request_1_resp_command
*)msg->payload;
response->hdr.command = NSM_FW_IRREVERSABLE_CONFIGURATION;
response->hdr.completion_code = cc;
uint16_t msg_size = sizeof(struct nsm_common_resp);
response->hdr.data_size = htole16(msg_size);
return NSM_SW_SUCCESS;
}
int encode_nsm_firmware_irreversible_config_request_2_resp(
uint8_t instance_id, uint8_t cc, uint16_t reason_code,
struct nsm_firmware_irreversible_config_request_2_resp *cfg_resp,
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_FIRMWARE;
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_FW_IRREVERSABLE_CONFIGURATION, msg);
}
struct nsm_firmware_irreversible_config_request_2_resp_command
*response =
(struct nsm_firmware_irreversible_config_request_2_resp_command
*)msg->payload;
response->hdr.command = NSM_FW_IRREVERSABLE_CONFIGURATION;
response->hdr.completion_code = cc;
uint16_t msg_size =
sizeof(struct nsm_common_resp) +
sizeof(struct nsm_firmware_irreversible_config_request_2_resp);
response->hdr.data_size = htole16(msg_size);
memcpy(&(response->irreversible_cfg_enable_response), cfg_resp,
sizeof(struct nsm_firmware_irreversible_config_request_2_resp));
return NSM_SW_SUCCESS;
}
int decode_nsm_firmware_irreversible_config_request_0_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
struct nsm_firmware_irreversible_config_request_0_resp *cfg_resp)
{
if (msg == NULL || cfg_resp == 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_firmware_irreversible_config_request_0_resp)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_irreversible_config_request_0_resp_command *resp =
(struct nsm_firmware_irreversible_config_request_0_resp_command *)
msg->payload;
memcpy(cfg_resp, &(resp->irreversible_cfg_query),
sizeof(struct nsm_firmware_irreversible_config_request_0_resp));
return NSM_SW_SUCCESS;
}
int decode_nsm_firmware_irreversible_config_request_1_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code)
{
if (msg == 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)) {
return NSM_SW_ERROR_LENGTH;
}
return NSM_SW_SUCCESS;
}
int decode_nsm_firmware_irreversible_config_request_2_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
struct nsm_firmware_irreversible_config_request_2_resp *cfg_resp)
{
if (msg == NULL || cfg_resp == 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_firmware_irreversible_config_request_2_resp)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_irreversible_config_request_2_resp_command *resp =
(struct nsm_firmware_irreversible_config_request_2_resp_command *)
msg->payload;
memcpy(cfg_resp, &(resp->irreversible_cfg_enable_response),
sizeof(struct nsm_firmware_irreversible_config_request_2_resp));
return NSM_SW_SUCCESS;
}
int decode_nsm_code_auth_key_perm_query_req(
const struct nsm_msg *msg, size_t msg_len,
uint16_t *component_classification, uint16_t *component_identifier,
uint8_t *component_classification_index)
{
if (msg == NULL || component_classification == NULL ||
component_identifier == NULL ||
component_classification_index == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_code_auth_key_perm_query_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_code_auth_key_perm_query_req *req =
(struct nsm_code_auth_key_perm_query_req *)msg->payload;
if (req->hdr.data_size <
sizeof(struct nsm_code_auth_key_perm_query_req) -
NSM_REQUEST_CONVENTION_LEN) {
return NSM_SW_ERROR_DATA;
}
*component_classification = req->component_classification;
*component_identifier = req->component_identifier;
*component_classification_index = req->component_classification_index;
return NSM_SW_SUCCESS;
}
int encode_nsm_code_auth_key_perm_query_req(
uint8_t instance_id, uint16_t component_classification,
uint16_t component_identifier, uint8_t component_classification_index,
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_FIRMWARE;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_code_auth_key_perm_query_req *req =
(struct nsm_code_auth_key_perm_query_req *)msg->payload;
req->hdr.command = NSM_FW_QUERY_CODE_AUTH_KEY_PERM;
req->hdr.data_size =
htole16(sizeof(struct nsm_code_auth_key_perm_query_req) -
NSM_REQUEST_CONVENTION_LEN);
req->component_classification = component_classification;
req->component_identifier = component_identifier;
req->component_classification_index = component_classification_index;
return NSM_SUCCESS;
}
int decode_nsm_code_auth_key_perm_query_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code, uint16_t *active_component_key_index,
uint16_t *pending_component_key_index, uint8_t *permission_bitmap_length,
uint8_t *active_component_key_perm_bitmap,
uint8_t *pending_component_key_perm_bitmap, uint8_t *efuse_key_perm_bitmap,
uint8_t *pending_efuse_key_perm_bitmap)
{
if (msg == NULL || active_component_key_index == NULL ||
pending_component_key_index == NULL ||
permission_bitmap_length == 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;
}
size_t expected_bitmap_length =
msg_len - sizeof(struct nsm_msg_hdr) -
sizeof(struct nsm_code_auth_key_perm_query_resp);
struct nsm_code_auth_key_perm_query_resp *resp =
(struct nsm_code_auth_key_perm_query_resp *)msg->payload;
if (expected_bitmap_length !=
(size_t)resp->permission_bitmap_length * 4u) {
return NSM_SW_ERROR_LENGTH;
}
*active_component_key_index = resp->active_component_key_index;
*pending_component_key_index = resp->pending_component_key_index;
*permission_bitmap_length = resp->permission_bitmap_length;
if (active_component_key_perm_bitmap != NULL) {
const uint8_t *bitmap_ptr =
msg->payload +
sizeof(struct nsm_code_auth_key_perm_query_resp);
memcpy(active_component_key_perm_bitmap, bitmap_ptr,
resp->permission_bitmap_length);
}
if (pending_component_key_perm_bitmap != NULL) {
const uint8_t *bitmap_ptr =
msg->payload +
sizeof(struct nsm_code_auth_key_perm_query_resp) +
resp->permission_bitmap_length;
memcpy(pending_component_key_perm_bitmap, bitmap_ptr,
resp->permission_bitmap_length);
}
if (efuse_key_perm_bitmap != NULL) {
const uint8_t *bitmap_ptr =
msg->payload +
sizeof(struct nsm_code_auth_key_perm_query_resp) +
resp->permission_bitmap_length * 2u;
memcpy(efuse_key_perm_bitmap, bitmap_ptr,
resp->permission_bitmap_length);
}
if (pending_efuse_key_perm_bitmap != NULL) {
const uint8_t *bitmap_ptr =
msg->payload +
sizeof(struct nsm_code_auth_key_perm_query_resp) +
resp->permission_bitmap_length * 3u;
memcpy(pending_efuse_key_perm_bitmap, bitmap_ptr,
resp->permission_bitmap_length);
}
return NSM_SW_SUCCESS;
}
int encode_nsm_code_auth_key_perm_query_resp(
uint8_t instance_id, uint8_t cc, uint16_t reason_code,
uint16_t active_component_key_index, uint16_t pending_component_key_index,
uint8_t permission_bitmap_length, uint8_t *active_component_key_perm_bitmap,
uint8_t *pending_component_key_perm_bitmap, uint8_t *efuse_key_perm_bitmap,
uint8_t *pending_efuse_key_perm_bitmap, struct nsm_msg *msg)
{
if (msg == NULL || (permission_bitmap_length != 0 &&
(active_component_key_perm_bitmap == NULL ||
pending_component_key_perm_bitmap == NULL ||
efuse_key_perm_bitmap == NULL ||
pending_efuse_key_perm_bitmap == 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_FIRMWARE;
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_FW_QUERY_CODE_AUTH_KEY_PERM, msg);
}
struct nsm_code_auth_key_perm_query_resp *resp =
(struct nsm_code_auth_key_perm_query_resp *)msg->payload;
resp->hdr.command = NSM_FW_QUERY_CODE_AUTH_KEY_PERM;
resp->hdr.completion_code = cc;
resp->hdr.data_size =
htole16(sizeof(struct nsm_code_auth_key_perm_query_resp) -
NSM_RESPONSE_CONVENTION_LEN) +
permission_bitmap_length;
resp->active_component_key_index = active_component_key_index;
resp->pending_component_key_index = pending_component_key_index;
resp->permission_bitmap_length = permission_bitmap_length;
uint8_t *bitmap_ptr =
msg->payload + sizeof(struct nsm_code_auth_key_perm_query_resp);
memcpy(bitmap_ptr, active_component_key_perm_bitmap,
permission_bitmap_length);
bitmap_ptr += permission_bitmap_length;
memcpy(bitmap_ptr, pending_component_key_perm_bitmap,
permission_bitmap_length);
bitmap_ptr += permission_bitmap_length;
memcpy(bitmap_ptr, efuse_key_perm_bitmap, permission_bitmap_length);
bitmap_ptr += permission_bitmap_length;
memcpy(bitmap_ptr, pending_efuse_key_perm_bitmap,
permission_bitmap_length);
return NSM_SW_SUCCESS;
}
int decode_nsm_code_auth_key_perm_update_req(
const struct nsm_msg *msg, size_t msg_len,
enum nsm_code_auth_key_perm_request_type *request_type,
uint16_t *component_classification, uint16_t *component_identifier,
uint8_t *component_classification_index, uint64_t *nonce,
uint8_t *permission_bitmap_length, uint8_t *permission_bitmap)
{
if (msg == NULL || request_type == NULL ||
component_classification == NULL || component_identifier == NULL ||
component_classification_index == NULL || nonce == NULL ||
permission_bitmap_length == NULL) {
return NSM_SW_ERROR_NULL;
}
size_t expected_bitmap_length =
msg_len - sizeof(struct nsm_msg_hdr) -
sizeof(struct nsm_code_auth_key_perm_update_req);
struct nsm_code_auth_key_perm_update_req *req =
(struct nsm_code_auth_key_perm_update_req *)msg->payload;
if (expected_bitmap_length != req->permission_bitmap_length) {
return NSM_SW_ERROR_LENGTH;
}
if (req->request_type !=
NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_MOST_RESTRICTIVE_VALUE &&
req->request_type !=
NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_SPECIFIED_VALUE) {
return NSM_SW_ERROR_DATA;
}
*request_type = req->request_type;
*component_classification = req->component_classification;
*component_identifier = req->component_identifier;
*component_classification_index = req->component_classification_index;
*nonce = req->nonce;
*permission_bitmap_length = req->permission_bitmap_length;
if (permission_bitmap != NULL) {
const uint8_t *bitmap_ptr =
msg->payload +
sizeof(struct nsm_code_auth_key_perm_update_req);
memcpy(permission_bitmap, bitmap_ptr, expected_bitmap_length);
}
return NSM_SW_SUCCESS;
}
int encode_nsm_code_auth_key_perm_update_req(
uint8_t instance_id, enum nsm_code_auth_key_perm_request_type request_type,
uint16_t component_classification, uint16_t component_identifier,
uint8_t component_classification_index, uint64_t nonce,
uint8_t permission_bitmap_length, uint8_t *permission_bitmap,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
if (request_type !=
NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_MOST_RESTRICTIVE_VALUE &&
request_type !=
NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_SPECIFIED_VALUE) {
return NSM_SW_ERROR_DATA;
}
if (request_type ==
NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_MOST_RESTRICTIVE_VALUE &&
permission_bitmap_length != 0) {
return NSM_SW_ERROR_DATA;
}
if (request_type ==
NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_SPECIFIED_VALUE &&
(permission_bitmap_length == 0 || permission_bitmap == 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_FIRMWARE;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_code_auth_key_perm_update_req *req =
(struct nsm_code_auth_key_perm_update_req *)msg->payload;
req->hdr.command = NSM_FW_UPDATE_CODE_AUTH_KEY_PERM;
req->hdr.data_size =
htole16(sizeof(struct nsm_code_auth_key_perm_update_req) -
NSM_REQUEST_CONVENTION_LEN + permission_bitmap_length);
req->request_type = request_type;
req->component_classification = component_classification;
req->component_identifier = component_identifier;
req->component_classification_index = component_classification_index;
req->nonce = nonce;
req->permission_bitmap_length = permission_bitmap_length;
if (permission_bitmap_length != 0) {
uint8_t *bitmap_ptr =
msg->payload +
sizeof(struct nsm_code_auth_key_perm_update_req);
memcpy(bitmap_ptr, permission_bitmap, permission_bitmap_length);
}
return NSM_SUCCESS;
}
int decode_nsm_code_auth_key_perm_update_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
uint32_t *update_method)
{
if (msg == NULL || update_method == 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_code_auth_key_perm_update_resp)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_code_auth_key_perm_update_resp *resp =
(struct nsm_code_auth_key_perm_update_resp *)msg->payload;
if (resp->hdr.data_size <
sizeof(struct nsm_code_auth_key_perm_update_resp) -
NSM_RESPONSE_CONVENTION_LEN) {
return NSM_SW_ERROR_DATA;
}
*update_method = resp->update_method;
return NSM_SW_SUCCESS;
}
int encode_nsm_code_auth_key_perm_update_resp(uint8_t instance_id, uint8_t cc,
uint16_t reason_code,
uint32_t update_method,
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_FIRMWARE;
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_FW_UPDATE_CODE_AUTH_KEY_PERM, msg);
}
struct nsm_code_auth_key_perm_update_resp *resp =
(struct nsm_code_auth_key_perm_update_resp *)msg->payload;
resp->hdr.command = NSM_FW_UPDATE_CODE_AUTH_KEY_PERM;
resp->hdr.completion_code = cc;
resp->hdr.data_size =
htole16(sizeof(struct nsm_code_auth_key_perm_update_resp) -
NSM_RESPONSE_CONVENTION_LEN);
resp->update_method = update_method;
return NSM_SW_SUCCESS;
}
int encode_nsm_query_firmware_security_version_number_req(
uint8_t instance_id,
const struct nsm_firmware_security_version_number_req *fw_req,
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_FIRMWARE;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_firmware_security_version_number_req_command *request =
(struct nsm_firmware_security_version_number_req_command *)
msg->payload;
request->hdr.command = NSM_FW_QUERY_MIN_SECURITY_VERSION_NUMBER;
request->hdr.data_size =
sizeof(struct nsm_firmware_security_version_number_req);
memcpy(&request->fq_req, fw_req,
sizeof(struct nsm_firmware_security_version_number_req));
return NSM_SW_SUCCESS;
}
int decode_nsm_query_firmware_security_version_number_req(
const struct nsm_msg *msg, size_t msg_len,
struct nsm_firmware_security_version_number_req *fw_req)
{
if (msg == NULL || fw_req == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len <
sizeof(struct nsm_msg_hdr) +
sizeof(
struct nsm_firmware_security_version_number_req_command)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_security_version_number_req_command *request =
(struct nsm_firmware_security_version_number_req_command *)
msg->payload;
if (request->hdr.data_size < sizeof(*fw_req)) {
return NSM_SW_ERROR_DATA;
}
*fw_req = request->fq_req;
return NSM_SW_SUCCESS;
}
int encode_nsm_query_firmware_security_version_number_resp(
uint8_t instance_id, uint8_t cc, uint16_t reason_code,
struct nsm_firmware_security_version_number_resp *sec_info,
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_FIRMWARE;
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_FW_QUERY_MIN_SECURITY_VERSION_NUMBER,
msg);
}
struct nsm_firmware_security_version_number_resp_command *response =
(struct nsm_firmware_security_version_number_resp_command *)
msg->payload;
response->hdr.command = NSM_FW_QUERY_MIN_SECURITY_VERSION_NUMBER;
response->hdr.completion_code = cc;
uint16_t msg_size =
sizeof(struct nsm_common_resp) +
sizeof(struct nsm_firmware_security_version_number_resp);
response->hdr.data_size = htole16(msg_size);
memcpy(&(response->sec_ver_resp), sec_info,
sizeof(struct nsm_firmware_security_version_number_resp));
return NSM_SW_SUCCESS;
}
int decode_nsm_query_firmware_security_version_number_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
struct nsm_firmware_security_version_number_resp *sec_resp)
{
if (msg == NULL || sec_resp == 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_firmware_security_version_number_resp_command)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_security_version_number_resp_command *resp =
(struct nsm_firmware_security_version_number_resp_command *)
msg->payload;
memcpy(sec_resp, &(resp->sec_ver_resp),
sizeof(struct nsm_firmware_security_version_number_resp));
return NSM_SW_SUCCESS;
}
int encode_nsm_firmware_update_sec_ver_req(
uint8_t instance_id,
const struct nsm_firmware_update_min_sec_ver_req *fw_req,
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_FIRMWARE;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_firmware_update_min_sec_ver_req_command *request =
(struct nsm_firmware_update_min_sec_ver_req_command *)msg->payload;
request->hdr.command = NSM_FW_UPDATE_MIN_SECURITY_VERSION_NUMBER;
request->hdr.data_size =
sizeof(struct nsm_firmware_update_min_sec_ver_req);
memcpy(&request->ver_update_req, fw_req,
sizeof(struct nsm_firmware_update_min_sec_ver_req));
return NSM_SW_SUCCESS;
}
int decode_nsm_firmware_update_sec_ver_req(
const struct nsm_msg *msg, size_t msg_len,
struct nsm_firmware_update_min_sec_ver_req *fw_req)
{
if (msg == NULL || fw_req == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_firmware_update_min_sec_ver_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_update_min_sec_ver_req_command *request =
(struct nsm_firmware_update_min_sec_ver_req_command *)msg->payload;
if (request->hdr.data_size < sizeof(*fw_req)) {
return NSM_SW_ERROR_DATA;
}
*fw_req = request->ver_update_req;
return NSM_SW_SUCCESS;
}
int encode_nsm_firmware_update_sec_ver_resp(
uint8_t instance_id, uint8_t cc, uint16_t reason_code,
struct nsm_firmware_update_min_sec_ver_resp *sec_resp, 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_FIRMWARE;
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_FW_UPDATE_MIN_SECURITY_VERSION_NUMBER,
msg);
}
struct nsm_firmware_update_min_sec_ver_resp_command *response =
(struct nsm_firmware_update_min_sec_ver_resp_command *)msg->payload;
response->hdr.command = NSM_FW_UPDATE_MIN_SECURITY_VERSION_NUMBER;
response->hdr.completion_code = cc;
uint16_t msg_size = sizeof(struct nsm_common_resp) +
sizeof(struct nsm_firmware_update_min_sec_ver_resp);
response->hdr.data_size = htole16(msg_size);
memcpy(&(response->sec_ver_resp), sec_resp,
sizeof(struct nsm_firmware_update_min_sec_ver_resp));
return NSM_SW_SUCCESS;
}
int decode_nsm_firmware_update_sec_ver_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
struct nsm_firmware_update_min_sec_ver_resp *sec_resp)
{
if (msg == NULL || sec_resp == 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_firmware_update_min_sec_ver_resp)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_update_min_sec_ver_resp_command *resp =
(struct nsm_firmware_update_min_sec_ver_resp_command *)msg->payload;
memcpy(sec_resp, &(resp->sec_ver_resp),
sizeof(struct nsm_firmware_update_min_sec_ver_resp));
return NSM_SW_SUCCESS;
}
int encode_nsm_firmware_set_rot_property_req(
uint8_t instance_id, const struct nsm_firmware_set_rot_property_req *fw_req,
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_FIRMWARE;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_firmware_set_rot_property_req_command *request =
(struct nsm_firmware_set_rot_property_req_command *)msg->payload;
request->hdr.command = NSM_FW_SET_ROT_PROPERTY;
request->hdr.data_size =
sizeof(struct nsm_firmware_set_rot_property_req);
memcpy(&request->rot_property_req, fw_req,
sizeof(struct nsm_firmware_set_rot_property_req));
return NSM_SW_SUCCESS;
}
int decode_nsm_firmware_set_rot_property_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc,
uint16_t *reason_code)
{
if (msg == 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_firmware_set_rot_property_resp_command)) {
return NSM_SW_ERROR_LENGTH;
}
return NSM_SW_SUCCESS;
}
int encode_nsm_firmware_set_rot_property_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_FIRMWARE;
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_FW_SET_ROT_PROPERTY, msg);
}
struct nsm_firmware_set_rot_property_resp_command *response =
(struct nsm_firmware_set_rot_property_resp_command *)msg->payload;
response->hdr.command = NSM_FW_SET_ROT_PROPERTY;
response->hdr.completion_code = cc;
return NSM_SW_SUCCESS;
}
int encode_nsm_dot_cak_install_req(
uint8_t instance_id, const struct nsm_dot_cak_install_req *dot_cak_req,
struct nsm_msg *msg)
{
if (msg == NULL || dot_cak_req == 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_FIRMWARE;
uint8_t rc = pack_nsm_header_v2(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_dot_cak_install_req_command *request =
(struct nsm_dot_cak_install_req_command *)msg->payload;
request->hdr.command = NSM_FW_DOT_CAK_INSTALL;
request->hdr.reserved1 = 0;
request->hdr.reserved2 = 0;
request->hdr.data_size =
htole16(sizeof(struct nsm_dot_cak_install_req));
memcpy(&(request->dot_cak_install_req), dot_cak_req,
sizeof(struct nsm_dot_cak_install_req));
return NSM_SW_SUCCESS;
}
int decode_nsm_dot_cak_install_req(const struct nsm_msg *msg, size_t msg_len,
struct nsm_dot_cak_install_req *dot_cak_req)
{
if (msg == NULL || dot_cak_req == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_dot_cak_install_req_command)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_dot_cak_install_req_command *request =
(struct nsm_dot_cak_install_req_command *)msg->payload;
// data_size validation removed - not required for this function
*dot_cak_req = request->dot_cak_install_req;
return NSM_SW_SUCCESS;
}
int encode_nsm_dot_cak_install_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_FIRMWARE;
uint8_t rc = pack_nsm_header_v2(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_FW_DOT_CAK_INSTALL, msg);
}
struct nsm_common_resp *response =
(struct nsm_common_resp *)msg->payload;
response->command = NSM_FW_DOT_CAK_INSTALL;
response->completion_code = cc;
response->reserved = 0;
response->data_size = 0; // No additional data for DOT CAK Install
return NSM_SW_SUCCESS;
}
int decode_nsm_dot_cak_install_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;
}
// For success case, set reason_code to ERR_NULL
*reason_code = ERR_NULL;
if (msg_len <
sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
return NSM_SW_ERROR_LENGTH;
}
return NSM_SW_SUCCESS;
}
int encode_nsm_dot_cak_bypass_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_FIRMWARE;
uint8_t rc = pack_nsm_header_v2(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
nsm_dot_cak_bypass_req *request =
(nsm_dot_cak_bypass_req *)msg->payload;
request->command = NSM_FW_DOT_CAK_BYPASS;
request->reserved1 = 0;
request->reserved2 = 0;
request->data_size = 0; // No additional data
return NSM_SW_SUCCESS;
}
int decode_nsm_dot_cak_bypass_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_dot_cak_bypass_req)) {
return NSM_SW_ERROR_LENGTH;
}
return NSM_SW_SUCCESS;
}
int encode_nsm_dot_cak_bypass_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_FIRMWARE;
uint8_t rc = pack_nsm_header_v2(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_FW_DOT_CAK_BYPASS, msg);
}
nsm_dot_cak_bypass_resp *response =
(nsm_dot_cak_bypass_resp *)msg->payload;
response->command = NSM_FW_DOT_CAK_BYPASS;
response->completion_code = cc;
response->reserved = 0;
response->data_size = 0;
return NSM_SW_SUCCESS;
}
int decode_nsm_dot_cak_bypass_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;
}
// For success case, set reason_code to ERR_NULL
*reason_code = ERR_NULL;
return NSM_SW_SUCCESS;
}
int encode_nsm_firmware_image_copy_control_req(
uint8_t instance_id,
const struct nsm_firmware_image_copy_control_req *fw_req,
const struct nsm_firmware_image_copy_component_entry *component_entries,
struct nsm_msg *msg)
{
if (msg == NULL || fw_req == NULL) {
return NSM_SW_ERROR_NULL;
}
// Validate component_entries if component_count > 0
if (fw_req->component_count > 0 && component_entries == 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_FIRMWARE;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_firmware_image_copy_control_req_command *request =
(struct nsm_firmware_image_copy_control_req_command *)msg->payload;
request->hdr.command = NSM_FW_IMAGE_COPY_CONTROL;
request->hdr.data_size =
htole16(sizeof(struct nsm_firmware_image_copy_control_req) +
(fw_req->component_count *
sizeof(struct nsm_firmware_image_copy_component_entry)));
memcpy(&request->image_copy_control_req, fw_req,
sizeof(struct nsm_firmware_image_copy_control_req));
// Encode component entries if present
if (fw_req->component_count > 0) {
uint8_t *component_data =
msg->payload + sizeof(struct nsm_common_req) +
sizeof(struct nsm_firmware_image_copy_control_req);
for (uint8_t i = 0; i < fw_req->component_count; ++i) {
struct nsm_firmware_image_copy_component_entry *entry =
(struct nsm_firmware_image_copy_component_entry *)
component_data;
entry->component_classification = htole16(
component_entries[i].component_classification);
entry->component_identifier =
htole16(component_entries[i].component_identifier);
entry->component_classification_index =
component_entries[i].component_classification_index;
component_data += sizeof(
struct nsm_firmware_image_copy_component_entry);
}
}
return NSM_SW_SUCCESS;
}
int decode_nsm_firmware_image_copy_control_query_progress_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
struct nsm_firmware_image_copy_control_query_progress_resp
*image_copy_control_query)
{
if (msg == NULL || image_copy_control_query == 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_firmware_image_copy_control_query_progress_resp_command)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_firmware_image_copy_control_query_progress_resp_command
*resp =
(struct
nsm_firmware_image_copy_control_query_progress_resp_command *)
msg->payload;
memcpy(
image_copy_control_query, &(resp->image_copy_control_query),
sizeof(struct nsm_firmware_image_copy_control_query_progress_resp));
return NSM_SW_SUCCESS;
}
int decode_nsm_firmware_image_copy_control_initiate_copy_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr)) {
return NSM_SW_ERROR_LENGTH;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
return NSM_SW_SUCCESS;
}