blob: 34081d4133048de3e4c0d9771e604df8cfc3ebcd [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 "device-capability-discovery.h"
#include "base.h"
#include <endian.h>
#include <stdio.h>
#include <string.h>
int encode_nsm_get_supported_event_source_req(uint8_t instance_id,
uint8_t nvidia_message_type,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_ERR_INVALID_DATA;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id & 0x1f;
header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_get_supported_event_source_req *request =
(struct nsm_get_supported_event_source_req *)msg->payload;
request->hdr.command = NSM_GET_CURRENT_EVENT_SOURCES;
request->hdr.data_size = NSM_GET_CURRENT_EVENT_SOURCES_REQ_DATA_SIZE;
request->nvidia_message_type = nvidia_message_type;
return NSM_SUCCESS;
}
int decode_nsm_get_supported_event_source_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
bitfield8_t supported_event_sources[EVENT_SOURCES_LENGTH])
{
if (msg == NULL || cc == NULL) {
return NSM_ERR_INVALID_DATA;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_supported_event_source_resp)) {
return NSM_ERR_INVALID_DATA;
}
struct nsm_get_supported_event_source_resp *response =
(struct nsm_get_supported_event_source_resp *)msg->payload;
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
memcpy(supported_event_sources, response->supported_event_sources,
EVENT_SOURCES_LENGTH);
return NSM_SUCCESS;
}
int encode_nsm_get_event_subscription_req(uint8_t instance_id,
struct nsm_msg *msg)
{
return encode_common_req(instance_id,
NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY,
NSM_GET_EVENT_SUBSCRIPTION, msg);
}
int decode_nsm_get_event_subscription_req(const struct nsm_msg *msg,
size_t msg_len)
{
return decode_common_req(msg, msg_len);
}
int encode_nsm_get_event_subscription_resp(uint8_t instance_id, uint8_t cc,
uint16_t reason_code,
uint8_t receiver_eid,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {NSM_RESPONSE, instance_id,
NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY};
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_GET_EVENT_SUBSCRIPTION, msg);
}
struct nsm_get_event_subscription_resp *response =
(struct nsm_get_event_subscription_resp *)msg->payload;
response->hdr.command = NSM_GET_EVENT_SUBSCRIPTION;
response->hdr.completion_code = cc;
response->hdr.data_size = htole16(1);
response->receiver_endpoint_id = receiver_eid;
return NSM_SUCCESS;
}
int decode_nsm_get_event_subscription_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
uint8_t *receiver_eid)
{
if (msg == NULL || receiver_eid == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
uint8_t rc = unpack_nsm_header(&msg->hdr, &header);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
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_event_subscription_resp)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_event_subscription_resp *response =
(struct nsm_get_event_subscription_resp *)msg->payload;
response->hdr.data_size = le16toh(response->hdr.data_size);
if (response->hdr.data_size != 1) {
return NSM_SW_ERROR_LENGTH;
}
*receiver_eid = response->receiver_endpoint_id;
return NSM_SUCCESS;
}
int encode_nsm_set_event_subscription_req(uint8_t instance_id,
uint8_t global_setting,
uint8_t receiver_eid,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_ERR_INVALID_DATA;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id & 0x1f;
header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_set_event_subscription_req *request =
(struct nsm_set_event_subscription_req *)msg->payload;
request->hdr.command = NSM_SET_EVENT_SUBSCRIPTION;
request->hdr.data_size = NSM_SET_EVENT_SUBSCRIPTION_REQ_DATA_SIZE;
request->global_event_generation_setting = global_setting;
request->receiver_endpoint_id = receiver_eid;
return NSM_SUCCESS;
}
int decode_nsm_set_event_subscription_req(const struct nsm_msg *msg,
size_t msg_len,
uint8_t *global_setting,
uint8_t *receiver_eid)
{
if (msg == NULL || global_setting == NULL || receiver_eid == NULL) {
return NSM_ERR_INVALID_DATA;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_set_event_subscription_req)) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
struct nsm_set_event_subscription_req *request =
(struct nsm_set_event_subscription_req *)msg->payload;
if (request->hdr.data_size < NSM_SET_EVENT_SUBSCRIPTION_REQ_DATA_SIZE) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
*global_setting = request->global_event_generation_setting;
*receiver_eid = request->receiver_endpoint_id;
return NSM_SUCCESS;
}
int decode_nsm_set_event_subscription_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc)
{
if (msg == NULL || cc == NULL) {
return NSM_ERR_INVALID_DATA;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_set_event_subscription_resp)) {
return NSM_ERR_INVALID_DATA;
}
struct nsm_set_event_subscription_resp *response =
(struct nsm_set_event_subscription_resp *)msg->payload;
*cc = response->hdr.completion_code;
return NSM_SUCCESS;
}
int encode_nsm_configure_event_acknowledgement_req(
uint8_t instance_id, uint8_t nvidia_message_type,
bitfield8_t *current_event_sources_acknowledgement_mask,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_ERR_INVALID_DATA;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id & 0x1f;
header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_configure_event_acknowledgement_req *request =
(struct nsm_configure_event_acknowledgement_req *)msg->payload;
request->hdr.command = NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT;
request->hdr.data_size =
NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT_REQ_DATA_SIZE;
request->nvidia_message_type = nvidia_message_type;
memcpy(request->current_event_sources_acknowledgement_mask,
current_event_sources_acknowledgement_mask,
EVENT_ACKNOWLEDGEMENT_MASK_LENGTH);
return NSM_SUCCESS;
}
int decode_nsm_configure_event_acknowledgement_req(
const struct nsm_msg *msg, size_t msg_len, uint8_t *nvidia_message_type,
bitfield8_t **current_event_sources_acknowledgement_mask)
{
if (msg == NULL || nvidia_message_type == NULL ||
current_event_sources_acknowledgement_mask == NULL) {
return NSM_ERR_INVALID_DATA;
}
if (msg_len <
sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_configure_event_acknowledgement_req)) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
struct nsm_configure_event_acknowledgement_req *request =
(struct nsm_configure_event_acknowledgement_req *)msg->payload;
if (request->hdr.data_size <
NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT_REQ_DATA_SIZE) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
*nvidia_message_type = request->nvidia_message_type;
*current_event_sources_acknowledgement_mask =
request->current_event_sources_acknowledgement_mask;
return NSM_SUCCESS;
}
int encode_nsm_configure_event_acknowledgement_resp(
uint8_t instance_id, uint8_t cc,
bitfield8_t *new_event_sources_acknowledgement_mask, struct nsm_msg *msg)
{
if (new_event_sources_acknowledgement_mask == NULL || msg == NULL) {
return NSM_ERR_INVALID_DATA;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance_id & 0x1f;
header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_configure_event_acknowledgement_resp *response =
(struct nsm_configure_event_acknowledgement_resp *)msg->payload;
response->hdr.command = NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT;
response->hdr.completion_code = cc;
response->hdr.reserved = 0;
response->hdr.data_size = htole16(EVENT_ACKNOWLEDGEMENT_MASK_LENGTH);
memcpy(response->new_event_sources_acknowledgement_mask,
new_event_sources_acknowledgement_mask,
EVENT_ACKNOWLEDGEMENT_MASK_LENGTH);
return NSM_SUCCESS;
}
int decode_nsm_configure_event_acknowledgement_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
bitfield8_t **new_event_sources_acknowledgement_mask)
{
if (msg == NULL || cc == NULL) {
return NSM_ERR_INVALID_DATA;
}
if (msg_len <
sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_configure_event_acknowledgement_resp)) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
struct nsm_configure_event_acknowledgement_resp *response =
(struct nsm_configure_event_acknowledgement_resp *)msg->payload;
*cc = response->hdr.completion_code;
*new_event_sources_acknowledgement_mask =
response->new_event_sources_acknowledgement_mask;
return NSM_SUCCESS;
}
int encode_nsm_set_current_event_sources_req(uint8_t instance_id,
uint8_t nvidia_message_type,
bitfield8_t *event_sources,
struct nsm_msg *msg)
{
if (event_sources == NULL || msg == NULL) {
return NSM_ERR_INVALID_DATA;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id & 0x1f;
header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_set_current_event_source_req *request =
(struct nsm_set_current_event_source_req *)msg->payload;
request->hdr.command = NSM_SET_CURRENT_EVENT_SOURCES;
request->hdr.data_size = NSM_SET_CURRENT_EVENT_SOURCES_REQ_DATA_SIZE;
request->nvidia_message_type = nvidia_message_type;
memcpy(request->event_sources, event_sources, EVENT_SOURCES_LENGTH);
return NSM_SUCCESS;
}
int decode_nsm_set_current_event_source_req(const struct nsm_msg *msg,
size_t msg_len,
uint8_t *nvidia_message_type,
bitfield8_t **event_sources)
{
if (msg == NULL || nvidia_message_type == NULL ||
event_sources == NULL) {
return NSM_ERR_INVALID_DATA;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_set_current_event_source_req)) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
struct nsm_set_current_event_source_req *request =
(struct nsm_set_current_event_source_req *)msg->payload;
if (request->hdr.data_size !=
NSM_SET_CURRENT_EVENT_SOURCES_REQ_DATA_SIZE) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
*nvidia_message_type = request->nvidia_message_type;
*event_sources = request->event_sources;
return NSM_SUCCESS;
}
int decode_nsm_set_current_event_sources_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc)
{
if (msg == NULL || cc == NULL) {
return NSM_ERR_INVALID_DATA;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_set_current_event_source_resp)) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
struct nsm_set_current_event_source_resp *response =
(struct nsm_set_current_event_source_resp *)msg->payload;
*cc = response->hdr.completion_code;
return NSM_SUCCESS;
}
int encode_nsm_get_event_log_record_req(uint8_t instance_id,
uint8_t selector_type,
uint32_t selector, struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_ERR_INVALID_DATA;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id & 0x1f;
header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SUCCESS) {
return rc;
}
struct nsm_get_event_log_record_req *request =
(struct nsm_get_event_log_record_req *)msg->payload;
request->hdr.command = NSM_GET_EVENT_LOG_RECORD;
request->hdr.data_size = 5;
request->selector_type = selector_type;
request->selector = htole32(selector);
return NSM_SUCCESS;
}
int decode_nsm_get_event_log_record_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint8_t *nvidia_message_type, uint8_t *event_id, uint32_t *event_handle,
uint64_t *timestamp, uint8_t **payload, uint16_t *payload_len)
{
if (msg == NULL || cc == NULL) {
return NSM_ERR_INVALID_DATA;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_event_log_record_resp) - 1) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
struct nsm_get_event_log_record_resp *response =
(struct nsm_get_event_log_record_resp *)msg->payload;
*cc = response->hdr.completion_code;
*nvidia_message_type = response->nvidia_message_type;
*event_id = response->event_id;
*event_handle = le32toh(response->event_handle);
*timestamp = le64toh(response->timestamp);
uint16_t data_size = le16toh(response->hdr.data_size);
if (data_size > NSM_GET_EVENT_LOG_RECORD_RESP_MIN_DATA_SIZE) {
*payload = response->payload;
*payload_len =
data_size - NSM_GET_EVENT_LOG_RECORD_RESP_MIN_DATA_SIZE;
}
return NSM_SUCCESS;
}
int encode_nsm_rediscovery_event(uint8_t instance_id, bool ackr,
struct nsm_msg *msg)
{
return encode_nsm_event(instance_id,
NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY, ackr,
NSM_EVENT_VERSION, NSM_REDISCOVERY_EVENT,
NSM_GENERAL_EVENT_CLASS, 0, 0, NULL, msg);
}
int decode_nsm_rediscovery_event(const struct nsm_msg *msg, size_t msg_len,
uint8_t *event_class, uint16_t *event_state)
{
if (msg == NULL || event_class == NULL || event_state == NULL) {
return NSM_ERR_INVALID_DATA;
}
if (msg_len < sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
struct nsm_event *event = (struct nsm_event *)msg->payload;
if (event->data_size > 0) {
return NSM_ERR_INVALID_DATA_LENGTH;
}
*event_class = event->event_class;
*event_state = le16toh(event->event_state);
return NSM_SUCCESS;
}