Coverage Report

Created: 2026-07-25 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nsmd/libnsm/device-capability-discovery.c
Line
Count
Source
1
/*
2
 * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION &
3
 * AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#include "device-capability-discovery.h"
19
#include "base.h"
20
#include <endian.h>
21
#include <stdio.h>
22
#include <string.h>
23
24
int encode_nsm_get_supported_event_source_req(uint8_t instance_id,
25
                uint8_t nvidia_message_type,
26
                struct nsm_msg *msg)
27
0
{
28
0
  if (msg == NULL) {
29
0
    return NSM_ERR_INVALID_DATA;
30
0
  }
31
32
0
  struct nsm_header_info header = {0};
33
0
  header.nsm_msg_type = NSM_REQUEST;
34
0
  header.instance_id = instance_id & 0x1f;
35
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
36
37
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
38
0
  if (rc != NSM_SUCCESS) {
39
0
    return rc;
40
0
  }
41
42
0
  struct nsm_get_supported_event_source_req *request =
43
0
      (struct nsm_get_supported_event_source_req *)msg->payload;
44
45
0
  request->hdr.command = NSM_GET_CURRENT_EVENT_SOURCES;
46
0
  request->hdr.data_size = NSM_GET_CURRENT_EVENT_SOURCES_REQ_DATA_SIZE;
47
0
  request->nvidia_message_type = nvidia_message_type;
48
49
0
  return NSM_SUCCESS;
50
0
}
51
52
int decode_nsm_get_supported_event_source_resp(
53
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
54
    uint16_t *reason_code,
55
    bitfield8_t supported_event_sources[EVENT_SOURCES_LENGTH])
56
0
{
57
0
  if (msg == NULL || cc == NULL) {
58
0
    return NSM_ERR_INVALID_DATA;
59
0
  }
60
61
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
62
0
        sizeof(struct nsm_get_supported_event_source_resp)) {
63
0
    return NSM_ERR_INVALID_DATA;
64
0
  }
65
66
0
  struct nsm_get_supported_event_source_resp *response =
67
0
      (struct nsm_get_supported_event_source_resp *)msg->payload;
68
69
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
70
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
71
0
    return rc;
72
0
  }
73
74
0
  memcpy(supported_event_sources, response->supported_event_sources,
75
0
         EVENT_SOURCES_LENGTH);
76
77
0
  return NSM_SUCCESS;
78
0
}
79
80
int encode_nsm_get_event_subscription_req(uint8_t instance_id,
81
            struct nsm_msg *msg)
82
0
{
83
0
  return encode_common_req(instance_id,
84
0
         NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY,
85
0
         NSM_GET_EVENT_SUBSCRIPTION, msg);
86
0
}
87
88
int decode_nsm_get_event_subscription_req(const struct nsm_msg *msg,
89
            size_t msg_len)
90
0
{
91
0
  return decode_common_req(msg, msg_len);
92
0
}
93
94
int encode_nsm_get_event_subscription_resp(uint8_t instance_id, uint8_t cc,
95
             uint16_t reason_code,
96
             uint8_t receiver_eid,
97
             struct nsm_msg *msg)
98
0
{
99
0
  if (msg == NULL) {
100
0
    return NSM_SW_ERROR_NULL;
101
0
  }
102
103
0
  struct nsm_header_info header = {NSM_RESPONSE, instance_id,
104
0
           NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY};
105
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
106
0
  if (rc != NSM_SUCCESS) {
107
0
    return rc;
108
0
  }
109
110
0
  if (cc != NSM_SUCCESS) {
111
0
    return encode_reason_code(cc, reason_code,
112
0
            NSM_GET_EVENT_SUBSCRIPTION, msg);
113
0
  }
114
115
0
  struct nsm_get_event_subscription_resp *response =
116
0
      (struct nsm_get_event_subscription_resp *)msg->payload;
117
118
0
  response->hdr.command = NSM_GET_EVENT_SUBSCRIPTION;
119
0
  response->hdr.completion_code = cc;
120
0
  response->hdr.data_size = htole16(1);
121
0
  response->receiver_endpoint_id = receiver_eid;
122
123
0
  return NSM_SUCCESS;
124
0
}
125
126
int decode_nsm_get_event_subscription_resp(const struct nsm_msg *msg,
127
             size_t msg_len, uint8_t *cc,
128
             uint16_t *reason_code,
129
             uint8_t *receiver_eid)
130
0
{
131
0
  if (msg == NULL || receiver_eid == NULL) {
132
0
    return NSM_SW_ERROR_NULL;
133
0
  }
134
135
0
  struct nsm_header_info header = {0};
136
0
  uint8_t rc = unpack_nsm_header(&msg->hdr, &header);
137
0
  if (rc != NSM_SW_SUCCESS) {
138
0
    return rc;
139
0
  }
140
141
0
  rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
142
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
143
0
    return rc;
144
0
  }
145
146
0
  if (msg_len != sizeof(struct nsm_msg_hdr) +
147
0
         sizeof(struct nsm_get_event_subscription_resp)) {
148
0
    return NSM_SW_ERROR_LENGTH;
149
0
  }
150
151
0
  struct nsm_get_event_subscription_resp *response =
152
0
      (struct nsm_get_event_subscription_resp *)msg->payload;
153
154
0
  response->hdr.data_size = le16toh(response->hdr.data_size);
155
0
  if (response->hdr.data_size != 1) {
156
0
    return NSM_SW_ERROR_LENGTH;
157
0
  }
158
159
0
  *receiver_eid = response->receiver_endpoint_id;
160
161
0
  return NSM_SUCCESS;
162
0
}
163
164
int encode_nsm_set_event_subscription_req(uint8_t instance_id,
165
            uint8_t global_setting,
166
            uint8_t receiver_eid,
167
            struct nsm_msg *msg)
168
0
{
169
0
  if (msg == NULL) {
170
0
    return NSM_ERR_INVALID_DATA;
171
0
  }
172
173
0
  struct nsm_header_info header = {0};
174
0
  header.nsm_msg_type = NSM_REQUEST;
175
0
  header.instance_id = instance_id & 0x1f;
176
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
177
178
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
179
0
  if (rc != NSM_SUCCESS) {
180
0
    return rc;
181
0
  }
182
183
0
  struct nsm_set_event_subscription_req *request =
184
0
      (struct nsm_set_event_subscription_req *)msg->payload;
185
186
0
  request->hdr.command = NSM_SET_EVENT_SUBSCRIPTION;
187
0
  request->hdr.data_size = NSM_SET_EVENT_SUBSCRIPTION_REQ_DATA_SIZE;
188
0
  request->global_event_generation_setting = global_setting;
189
0
  request->receiver_endpoint_id = receiver_eid;
190
191
0
  return NSM_SUCCESS;
192
0
}
193
194
int decode_nsm_set_event_subscription_req(const struct nsm_msg *msg,
195
            size_t msg_len,
196
            uint8_t *global_setting,
197
            uint8_t *receiver_eid)
198
0
{
199
0
  if (msg == NULL || global_setting == NULL || receiver_eid == NULL) {
200
0
    return NSM_ERR_INVALID_DATA;
201
0
  }
202
203
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
204
0
        sizeof(struct nsm_set_event_subscription_req)) {
205
0
    return NSM_ERR_INVALID_DATA_LENGTH;
206
0
  }
207
208
0
  struct nsm_set_event_subscription_req *request =
209
0
      (struct nsm_set_event_subscription_req *)msg->payload;
210
211
0
  if (request->hdr.data_size < NSM_SET_EVENT_SUBSCRIPTION_REQ_DATA_SIZE) {
212
0
    return NSM_ERR_INVALID_DATA_LENGTH;
213
0
  }
214
215
0
  *global_setting = request->global_event_generation_setting;
216
0
  *receiver_eid = request->receiver_endpoint_id;
217
218
0
  return NSM_SUCCESS;
219
0
}
220
221
int decode_nsm_set_event_subscription_resp(const struct nsm_msg *msg,
222
             size_t msg_len, uint8_t *cc)
223
0
{
224
0
  if (msg == NULL || cc == NULL) {
225
0
    return NSM_ERR_INVALID_DATA;
226
0
  }
227
228
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
229
0
        sizeof(struct nsm_set_event_subscription_resp)) {
230
0
    return NSM_ERR_INVALID_DATA;
231
0
  }
232
233
0
  struct nsm_set_event_subscription_resp *response =
234
0
      (struct nsm_set_event_subscription_resp *)msg->payload;
235
236
0
  *cc = response->hdr.completion_code;
237
238
0
  return NSM_SUCCESS;
239
0
}
240
241
int encode_nsm_configure_event_acknowledgement_req(
242
    uint8_t instance_id, uint8_t nvidia_message_type,
243
    bitfield8_t *current_event_sources_acknowledgement_mask,
244
    struct nsm_msg *msg)
245
0
{
246
0
  if (msg == NULL) {
247
0
    return NSM_ERR_INVALID_DATA;
248
0
  }
249
250
0
  struct nsm_header_info header = {0};
251
0
  header.nsm_msg_type = NSM_REQUEST;
252
0
  header.instance_id = instance_id & 0x1f;
253
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
254
255
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
256
0
  if (rc != NSM_SUCCESS) {
257
0
    return rc;
258
0
  }
259
260
0
  struct nsm_configure_event_acknowledgement_req *request =
261
0
      (struct nsm_configure_event_acknowledgement_req *)msg->payload;
262
263
0
  request->hdr.command = NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT;
264
0
  request->hdr.data_size =
265
0
      NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT_REQ_DATA_SIZE;
266
0
  request->nvidia_message_type = nvidia_message_type;
267
0
  memcpy(request->current_event_sources_acknowledgement_mask,
268
0
         current_event_sources_acknowledgement_mask,
269
0
         EVENT_ACKNOWLEDGEMENT_MASK_LENGTH);
270
271
0
  return NSM_SUCCESS;
272
0
}
273
274
int decode_nsm_configure_event_acknowledgement_req(
275
    const struct nsm_msg *msg, size_t msg_len, uint8_t *nvidia_message_type,
276
    bitfield8_t **current_event_sources_acknowledgement_mask)
277
0
{
278
0
  if (msg == NULL || nvidia_message_type == NULL ||
279
0
      current_event_sources_acknowledgement_mask == NULL) {
280
0
    return NSM_ERR_INVALID_DATA;
281
0
  }
282
283
0
  if (msg_len <
284
0
      sizeof(struct nsm_msg_hdr) +
285
0
    sizeof(struct nsm_configure_event_acknowledgement_req)) {
286
0
    return NSM_ERR_INVALID_DATA_LENGTH;
287
0
  }
288
289
0
  struct nsm_configure_event_acknowledgement_req *request =
290
0
      (struct nsm_configure_event_acknowledgement_req *)msg->payload;
291
292
0
  if (request->hdr.data_size <
293
0
      NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT_REQ_DATA_SIZE) {
294
0
    return NSM_ERR_INVALID_DATA_LENGTH;
295
0
  }
296
297
0
  *nvidia_message_type = request->nvidia_message_type;
298
0
  *current_event_sources_acknowledgement_mask =
299
0
      request->current_event_sources_acknowledgement_mask;
300
301
0
  return NSM_SUCCESS;
302
0
}
303
304
int encode_nsm_configure_event_acknowledgement_resp(
305
    uint8_t instance_id, uint8_t cc,
306
    bitfield8_t *new_event_sources_acknowledgement_mask, struct nsm_msg *msg)
307
0
{
308
0
  if (new_event_sources_acknowledgement_mask == NULL || msg == NULL) {
309
0
    return NSM_ERR_INVALID_DATA;
310
0
  }
311
312
0
  struct nsm_header_info header = {0};
313
0
  header.nsm_msg_type = NSM_RESPONSE;
314
0
  header.instance_id = instance_id & 0x1f;
315
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
316
317
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
318
0
  if (rc != NSM_SUCCESS) {
319
0
    return rc;
320
0
  }
321
322
0
  struct nsm_configure_event_acknowledgement_resp *response =
323
0
      (struct nsm_configure_event_acknowledgement_resp *)msg->payload;
324
325
0
  response->hdr.command = NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT;
326
0
  response->hdr.completion_code = cc;
327
0
  response->hdr.reserved = 0;
328
0
  response->hdr.data_size = htole16(EVENT_ACKNOWLEDGEMENT_MASK_LENGTH);
329
0
  memcpy(response->new_event_sources_acknowledgement_mask,
330
0
         new_event_sources_acknowledgement_mask,
331
0
         EVENT_ACKNOWLEDGEMENT_MASK_LENGTH);
332
0
  return NSM_SUCCESS;
333
0
}
334
335
int decode_nsm_configure_event_acknowledgement_resp(
336
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
337
    bitfield8_t **new_event_sources_acknowledgement_mask)
338
0
{
339
0
  if (msg == NULL || cc == NULL) {
340
0
    return NSM_ERR_INVALID_DATA;
341
0
  }
342
343
0
  if (msg_len <
344
0
      sizeof(struct nsm_msg_hdr) +
345
0
    sizeof(struct nsm_configure_event_acknowledgement_resp)) {
346
0
    return NSM_ERR_INVALID_DATA_LENGTH;
347
0
  }
348
349
0
  struct nsm_configure_event_acknowledgement_resp *response =
350
0
      (struct nsm_configure_event_acknowledgement_resp *)msg->payload;
351
352
0
  *cc = response->hdr.completion_code;
353
0
  *new_event_sources_acknowledgement_mask =
354
0
      response->new_event_sources_acknowledgement_mask;
355
356
0
  return NSM_SUCCESS;
357
0
}
358
359
int encode_nsm_set_current_event_sources_req(uint8_t instance_id,
360
               uint8_t nvidia_message_type,
361
               bitfield8_t *event_sources,
362
               struct nsm_msg *msg)
363
0
{
364
0
  if (event_sources == NULL || msg == NULL) {
365
0
    return NSM_ERR_INVALID_DATA;
366
0
  }
367
368
0
  struct nsm_header_info header = {0};
369
0
  header.nsm_msg_type = NSM_REQUEST;
370
0
  header.instance_id = instance_id & 0x1f;
371
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
372
373
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
374
0
  if (rc != NSM_SUCCESS) {
375
0
    return rc;
376
0
  }
377
378
0
  struct nsm_set_current_event_source_req *request =
379
0
      (struct nsm_set_current_event_source_req *)msg->payload;
380
381
0
  request->hdr.command = NSM_SET_CURRENT_EVENT_SOURCES;
382
0
  request->hdr.data_size = NSM_SET_CURRENT_EVENT_SOURCES_REQ_DATA_SIZE;
383
0
  request->nvidia_message_type = nvidia_message_type;
384
0
  memcpy(request->event_sources, event_sources, EVENT_SOURCES_LENGTH);
385
386
0
  return NSM_SUCCESS;
387
0
}
388
389
int decode_nsm_set_current_event_source_req(const struct nsm_msg *msg,
390
              size_t msg_len,
391
              uint8_t *nvidia_message_type,
392
              bitfield8_t **event_sources)
393
0
{
394
0
  if (msg == NULL || nvidia_message_type == NULL ||
395
0
      event_sources == NULL) {
396
0
    return NSM_ERR_INVALID_DATA;
397
0
  }
398
399
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
400
0
        sizeof(struct nsm_set_current_event_source_req)) {
401
0
    return NSM_ERR_INVALID_DATA_LENGTH;
402
0
  }
403
404
0
  struct nsm_set_current_event_source_req *request =
405
0
      (struct nsm_set_current_event_source_req *)msg->payload;
406
407
0
  if (request->hdr.data_size !=
408
0
      NSM_SET_CURRENT_EVENT_SOURCES_REQ_DATA_SIZE) {
409
0
    return NSM_ERR_INVALID_DATA_LENGTH;
410
0
  }
411
412
0
  *nvidia_message_type = request->nvidia_message_type;
413
0
  *event_sources = request->event_sources;
414
415
0
  return NSM_SUCCESS;
416
0
}
417
418
int decode_nsm_set_current_event_sources_resp(const struct nsm_msg *msg,
419
                size_t msg_len, uint8_t *cc)
420
0
{
421
0
  if (msg == NULL || cc == NULL) {
422
0
    return NSM_ERR_INVALID_DATA;
423
0
  }
424
425
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
426
0
        sizeof(struct nsm_set_current_event_source_resp)) {
427
0
    return NSM_ERR_INVALID_DATA_LENGTH;
428
0
  }
429
430
0
  struct nsm_set_current_event_source_resp *response =
431
0
      (struct nsm_set_current_event_source_resp *)msg->payload;
432
433
0
  *cc = response->hdr.completion_code;
434
435
0
  return NSM_SUCCESS;
436
0
}
437
438
int encode_nsm_get_event_log_record_req(uint8_t instance_id,
439
          uint8_t selector_type,
440
          uint32_t selector, struct nsm_msg *msg)
441
0
{
442
0
  if (msg == NULL) {
443
0
    return NSM_ERR_INVALID_DATA;
444
0
  }
445
446
0
  struct nsm_header_info header = {0};
447
0
  header.nsm_msg_type = NSM_REQUEST;
448
0
  header.instance_id = instance_id & 0x1f;
449
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
450
451
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
452
0
  if (rc != NSM_SUCCESS) {
453
0
    return rc;
454
0
  }
455
456
0
  struct nsm_get_event_log_record_req *request =
457
0
      (struct nsm_get_event_log_record_req *)msg->payload;
458
459
0
  request->hdr.command = NSM_GET_EVENT_LOG_RECORD;
460
0
  request->hdr.data_size = 5;
461
0
  request->selector_type = selector_type;
462
0
  request->selector = htole32(selector);
463
464
0
  return NSM_SUCCESS;
465
0
}
466
467
int decode_nsm_get_event_log_record_resp(
468
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
469
    uint8_t *nvidia_message_type, uint8_t *event_id, uint32_t *event_handle,
470
    uint64_t *timestamp, uint8_t **payload, uint16_t *payload_len)
471
0
{
472
0
  if (msg == NULL || cc == NULL) {
473
0
    return NSM_ERR_INVALID_DATA;
474
0
  }
475
476
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
477
0
        sizeof(struct nsm_get_event_log_record_resp) - 1) {
478
0
    return NSM_ERR_INVALID_DATA_LENGTH;
479
0
  }
480
481
0
  struct nsm_get_event_log_record_resp *response =
482
0
      (struct nsm_get_event_log_record_resp *)msg->payload;
483
484
0
  *cc = response->hdr.completion_code;
485
0
  *nvidia_message_type = response->nvidia_message_type;
486
0
  *event_id = response->event_id;
487
0
  *event_handle = le32toh(response->event_handle);
488
0
  *timestamp = le64toh(response->timestamp);
489
0
  uint16_t data_size = le16toh(response->hdr.data_size);
490
0
  if (data_size > NSM_GET_EVENT_LOG_RECORD_RESP_MIN_DATA_SIZE) {
491
0
    *payload = response->payload;
492
0
    *payload_len =
493
0
        data_size - NSM_GET_EVENT_LOG_RECORD_RESP_MIN_DATA_SIZE;
494
0
  }
495
496
0
  return NSM_SUCCESS;
497
0
}
498
499
int encode_nsm_rediscovery_event(uint8_t instance_id, bool ackr,
500
         struct nsm_msg *msg)
501
0
{
502
0
  return encode_nsm_event(instance_id,
503
0
        NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY, ackr,
504
0
        NSM_EVENT_VERSION, NSM_REDISCOVERY_EVENT,
505
0
        NSM_GENERAL_EVENT_CLASS, 0, 0, NULL, msg);
506
0
}
507
508
int decode_nsm_rediscovery_event(const struct nsm_msg *msg, size_t msg_len,
509
         uint8_t *event_class, uint16_t *event_state)
510
0
{
511
0
  if (msg == NULL || event_class == NULL || event_state == NULL) {
512
0
    return NSM_ERR_INVALID_DATA;
513
0
  }
514
515
0
  if (msg_len < sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN) {
516
0
    return NSM_ERR_INVALID_DATA_LENGTH;
517
0
  }
518
519
0
  struct nsm_event *event = (struct nsm_event *)msg->payload;
520
0
  if (event->data_size > 0) {
521
0
    return NSM_ERR_INVALID_DATA_LENGTH;
522
0
  }
523
524
0
  *event_class = event->event_class;
525
0
  *event_state = le16toh(event->event_state);
526
527
0
  return NSM_SUCCESS;
528
0
}