blob: f752d7ff78aa0e7d3362815f76bd1ab5f3e5147a [file] [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,
bitfield8_t **supported_event_sources)
{
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;
*cc = response->hdr.completion_code;
if (NSM_SUCCESS != *cc) {
return NSM_SUCCESS;
}
*supported_event_sources = response->supported_event_sources;
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;
}