Coverage Report

Created: 2026-10-28 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nsmd/libnsm/base.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 "base.h"
19
#include "device-capability-discovery.h"
20
21
#include <endian.h>
22
#include <limits.h>
23
#include <string.h>
24
25
uint8_t pack_nsm_header(const struct nsm_header_info *hdr,
26
      struct nsm_msg_hdr *msg)
27
0
{
28
0
  if (msg == NULL || hdr == NULL) {
29
0
    return NSM_SW_ERROR_NULL;
30
0
  }
31
32
0
  if (hdr->nsm_msg_type != NSM_RESPONSE &&
33
0
      hdr->nsm_msg_type != NSM_REQUEST &&
34
0
      hdr->nsm_msg_type != NSM_EVENT &&
35
0
      hdr->nsm_msg_type != NSM_EVENT_ACKNOWLEDGMENT) {
36
0
    return NSM_SW_ERROR_DATA;
37
0
  }
38
39
0
  if (hdr->instance_id > NSM_INSTANCE_MAX) {
40
0
    return NSM_SW_ERROR_DATA;
41
0
  }
42
43
0
  msg->datagram = 0;
44
0
  if (hdr->nsm_msg_type == NSM_EVENT_ACKNOWLEDGMENT ||
45
0
      hdr->nsm_msg_type == NSM_EVENT) {
46
0
    msg->datagram = 1;
47
0
  }
48
49
0
  msg->request = 0;
50
0
  if (hdr->nsm_msg_type == NSM_REQUEST ||
51
0
      hdr->nsm_msg_type == NSM_EVENT) {
52
0
    msg->request = 1;
53
0
  }
54
55
0
  msg->pci_vendor_id = htobe16(PCI_VENDOR_ID);
56
0
  msg->reserved = 0;
57
0
  msg->instance_id = hdr->instance_id;
58
0
  msg->ocp_type = OCP_TYPE;
59
0
  msg->ocp_version = OCP_VERSION;
60
0
  msg->nvidia_msg_type = hdr->nvidia_msg_type;
61
62
0
  return NSM_SW_SUCCESS;
63
0
}
64
65
uint8_t pack_nsm_header_v2(const struct nsm_header_info *hdr,
66
         struct nsm_msg_hdr *msg)
67
0
{
68
0
  uint8_t rc = pack_nsm_header(hdr, msg);
69
0
  if (rc == NSM_SW_SUCCESS) {
70
0
    msg->ocp_version = OCP_VERSION_V2;
71
0
  }
72
0
  return rc;
73
0
}
74
75
uint8_t unpack_nsm_header(const struct nsm_msg_hdr *msg,
76
        struct nsm_header_info *hdr)
77
1.19k
{
78
1.19k
  if (msg == NULL || hdr == NULL) {
79
0
    return NSM_SW_ERROR_NULL;
80
0
  }
81
82
1.19k
  if (be16toh(msg->pci_vendor_id) != PCI_VENDOR_ID) {
83
280
    return NSM_SW_ERROR_DATA;
84
280
  }
85
86
912
  if (msg->ocp_type != OCP_TYPE) {
87
95
    return NSM_SW_ERROR_DATA;
88
95
  }
89
90
817
  if (msg->ocp_version != OCP_VERSION &&
91
583
      msg->ocp_version != OCP_VERSION_V2) {
92
158
    return NSM_SW_ERROR_DATA;
93
158
  }
94
95
659
  if (msg->request == 0) {
96
101
    hdr->nsm_msg_type =
97
101
        msg->datagram ? NSM_EVENT_ACKNOWLEDGMENT : NSM_RESPONSE;
98
558
  } else {
99
558
    hdr->nsm_msg_type = msg->datagram ? NSM_EVENT : NSM_REQUEST;
100
558
  }
101
102
659
  hdr->instance_id = msg->instance_id;
103
659
  hdr->nvidia_msg_type = msg->nvidia_msg_type;
104
105
659
  return NSM_SW_SUCCESS;
106
817
}
107
108
static void htoleArrayData(uint8_t *data, uint16_t num_of_element,
109
         uint8_t data_type)
110
0
{
111
0
  switch (data_type) {
112
0
  case NvU8:
113
0
  case NvS8:
114
    // No operation for 8-bit types, just return
115
0
    break;
116
117
0
  case NvU16: {
118
0
    uint16_t tmp = 0;
119
0
    for (size_t i = 0; i < num_of_element; ++i) {
120
0
      memcpy(&tmp, data + (i * sizeof(uint16_t)),
121
0
             sizeof(uint16_t));
122
0
      tmp = htole16(tmp);
123
0
      memcpy(data + (i * sizeof(uint16_t)), &tmp,
124
0
             sizeof(uint16_t));
125
0
    }
126
0
  } break;
127
0
  case NvS16: {
128
0
    int16_t tmp = 0;
129
0
    for (size_t i = 0; i < num_of_element; ++i) {
130
0
      memcpy(&tmp, data + (i * sizeof(int16_t)),
131
0
             sizeof(int16_t));
132
0
      tmp = htole16(tmp);
133
0
      memcpy(data + (i * sizeof(int16_t)), &tmp,
134
0
             sizeof(int16_t));
135
0
    }
136
0
  } break;
137
138
0
  case NvU32: {
139
0
    uint32_t tmp = 0;
140
0
    for (size_t i = 0; i < num_of_element; ++i) {
141
0
      memcpy(&tmp, data + (i * sizeof(uint32_t)),
142
0
             sizeof(uint32_t));
143
0
      tmp = htole32(tmp);
144
0
      memcpy(data + (i * sizeof(uint32_t)), &tmp,
145
0
             sizeof(uint32_t));
146
0
    }
147
0
  } break;
148
0
  case NvS32: {
149
0
    int32_t tmp = 0;
150
0
    for (size_t i = 0; i < num_of_element; ++i) {
151
0
      memcpy(&tmp, data + (i * sizeof(int32_t)),
152
0
             sizeof(int32_t));
153
0
      tmp = htole32(tmp);
154
0
      memcpy(data + (i * sizeof(int32_t)), &tmp,
155
0
             sizeof(int32_t));
156
0
    }
157
0
  } break;
158
159
0
  case NvS24_8: {
160
0
    float tmp = 0;
161
0
    for (size_t i = 0; i < num_of_element; ++i) {
162
0
      memcpy(&tmp, data + (i * sizeof(float)), sizeof(float));
163
0
      tmp = htole32(tmp);
164
0
      memcpy(data + (i * sizeof(float)), &tmp, sizeof(float));
165
0
    }
166
0
  } break;
167
168
0
  case NvU64: {
169
0
    uint64_t tmp = 0;
170
0
    for (size_t i = 0; i < num_of_element; ++i) {
171
0
      memcpy(&tmp, data + (i * sizeof(uint64_t)),
172
0
             sizeof(uint64_t));
173
0
      tmp = htole64(tmp);
174
0
      memcpy(data + (i * sizeof(uint64_t)), &tmp,
175
0
             sizeof(uint64_t));
176
0
    }
177
0
  } break;
178
0
  case NvS64: {
179
0
    int64_t tmp = 0;
180
0
    for (size_t i = 0; i < num_of_element; ++i) {
181
0
      memcpy(&tmp, data + (i * sizeof(int64_t)),
182
0
             sizeof(int64_t));
183
0
      tmp = htole64(tmp);
184
0
      memcpy(data + (i * sizeof(int64_t)), &tmp,
185
0
             sizeof(int64_t));
186
0
    }
187
0
  } break;
188
189
0
  default:
190
    // No operation for unknown types
191
0
    break;
192
0
  }
193
0
}
194
195
static void letohArrayData(uint8_t *data, uint16_t num_of_element,
196
         uint8_t data_type)
197
121
{
198
121
  switch (data_type) {
199
32
  case NvU8:
200
34
  case NvS8:
201
    // No operation for 8-bit types, just return
202
34
    break;
203
204
2
  case NvU16: {
205
2
    uint16_t tmp = 0;
206
2
    for (size_t i = 0; i < num_of_element; ++i) {
207
0
      memcpy(&tmp, data + (i * sizeof(uint16_t)),
208
0
             sizeof(uint16_t));
209
0
      tmp = le16toh(tmp);
210
0
      memcpy(data + (i * sizeof(uint16_t)), &tmp,
211
0
             sizeof(uint16_t));
212
0
    }
213
2
  } break;
214
2
  case NvS16: {
215
2
    int16_t tmp = 0;
216
2
    for (size_t i = 0; i < num_of_element; ++i) {
217
0
      memcpy(&tmp, data + (i * sizeof(int16_t)),
218
0
             sizeof(int16_t));
219
0
      tmp = le16toh(tmp);
220
0
      memcpy(data + (i * sizeof(int16_t)), &tmp,
221
0
             sizeof(int16_t));
222
0
    }
223
2
  } break;
224
225
3
  case NvU32: {
226
3
    uint32_t tmp = 0;
227
3
    for (size_t i = 0; i < num_of_element; ++i) {
228
0
      memcpy(&tmp, data + (i * sizeof(uint32_t)),
229
0
             sizeof(uint32_t));
230
0
      tmp = le32toh(tmp);
231
0
      memcpy(data + (i * sizeof(uint32_t)), &tmp,
232
0
             sizeof(uint32_t));
233
0
    }
234
3
  } break;
235
2
  case NvS32: {
236
2
    int32_t tmp = 0;
237
2
    for (size_t i = 0; i < num_of_element; ++i) {
238
0
      memcpy(&tmp, data + (i * sizeof(int32_t)),
239
0
             sizeof(int32_t));
240
0
      tmp = le32toh(tmp);
241
0
      memcpy(data + (i * sizeof(int32_t)), &tmp,
242
0
             sizeof(int32_t));
243
0
    }
244
2
  } break;
245
246
54
  case NvS24_8: {
247
54
    float tmp = 0;
248
19.6k
    for (size_t i = 0; i < num_of_element; ++i) {
249
19.5k
      memcpy(&tmp, data + (i * sizeof(float)), sizeof(float));
250
19.5k
      tmp = le32toh(tmp);
251
19.5k
      memcpy(data + (i * sizeof(float)), &tmp, sizeof(float));
252
19.5k
    }
253
54
  } break;
254
255
2
  case NvU64: {
256
2
    uint64_t tmp = 0;
257
2
    for (size_t i = 0; i < num_of_element; ++i) {
258
0
      memcpy(&tmp, data + (i * sizeof(uint64_t)),
259
0
             sizeof(uint64_t));
260
0
      tmp = le64toh(tmp);
261
0
      memcpy(data + (i * sizeof(uint64_t)), &tmp,
262
0
             sizeof(uint64_t));
263
0
    }
264
2
  } break;
265
2
  case NvS64: {
266
2
    int64_t tmp = 0;
267
2
    for (size_t i = 0; i < num_of_element; ++i) {
268
0
      memcpy(&tmp, data + (i * sizeof(int64_t)),
269
0
             sizeof(int64_t));
270
0
      tmp = le64toh(tmp);
271
0
      memcpy(data + (i * sizeof(int64_t)), &tmp,
272
0
             sizeof(int64_t));
273
0
    }
274
2
  } break;
275
276
20
  default:
277
    // No operation for unknown types
278
20
    break;
279
121
  }
280
121
}
281
282
static void dataCopy(uint8_t *srcData, uint8_t *destData, uint16_t numOfElement,
283
         uint8_t dataType)
284
121
{
285
121
  size_t dataSize = 0;
286
121
  switch (dataType) {
287
32
  case NvU8:
288
32
    dataSize = sizeof(uint8_t) * numOfElement;
289
32
    break;
290
2
  case NvS8:
291
2
    dataSize = sizeof(int8_t) * numOfElement;
292
2
    break;
293
2
  case NvU16:
294
2
    dataSize = sizeof(uint16_t) * numOfElement;
295
2
    break;
296
2
  case NvS16:
297
2
    dataSize = sizeof(int16_t) * numOfElement;
298
2
    break;
299
3
  case NvU32:
300
3
    dataSize = sizeof(uint32_t) * numOfElement;
301
3
    break;
302
2
  case NvS32:
303
2
    dataSize = sizeof(int32_t) * numOfElement;
304
2
    break;
305
54
  case NvS24_8:
306
54
    dataSize = sizeof(float) * numOfElement;
307
54
    break;
308
2
  case NvU64:
309
2
    dataSize = sizeof(uint64_t) * numOfElement;
310
2
    break;
311
2
  case NvS64:
312
2
    dataSize = sizeof(int64_t) * numOfElement;
313
2
    break;
314
20
  default:
315
    // No operation for 8-bit types
316
20
    break;
317
121
  }
318
121
  memcpy(destData, srcData, dataSize);
319
121
}
320
321
int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
322
      uint8_t cc, uint16_t reason_code, struct nsm_msg *msg)
323
0
{
324
0
  if (msg == NULL) {
325
0
    return NSM_SW_ERROR_NULL;
326
0
  }
327
328
0
  struct nsm_header_info header = {0};
329
0
  header.nsm_msg_type = NSM_RESPONSE;
330
0
  header.instance_id = instance_id & INSTANCEID_MASK;
331
0
  header.nvidia_msg_type = type;
332
333
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
334
0
  if (rc != NSM_SW_SUCCESS) {
335
0
    return rc;
336
0
  }
337
338
0
  if (cc != NSM_SUCCESS) {
339
0
    return encode_reason_code(cc, reason_code, command, msg);
340
0
  }
341
342
0
  struct nsm_common_resp *response =
343
0
      (struct nsm_common_resp *)msg->payload;
344
345
0
  response->command = command;
346
0
  response->completion_code = cc;
347
0
  response->data_size = 0;
348
349
0
  return NSM_SW_SUCCESS;
350
0
}
351
352
int encode_ping_req(uint8_t instance_id, struct nsm_msg *msg)
353
0
{
354
0
  if (msg == NULL) {
355
0
    return NSM_SW_ERROR_NULL;
356
0
  }
357
358
0
  struct nsm_header_info header = {0};
359
0
  header.nsm_msg_type = NSM_REQUEST;
360
0
  header.instance_id = instance_id;
361
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
362
363
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
364
0
  if (rc != NSM_SW_SUCCESS) {
365
0
    return rc;
366
0
  }
367
368
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
369
370
0
  request->command = NSM_PING;
371
0
  request->data_size = 0;
372
373
0
  return NSM_SW_SUCCESS;
374
0
}
375
376
int encode_ping_resp(uint8_t instance_id, uint16_t reason_code,
377
         struct nsm_msg *msg)
378
0
{
379
0
  return encode_cc_only_resp(instance_id,
380
0
           NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY,
381
0
           NSM_PING, NSM_SUCCESS, reason_code, msg);
382
0
}
383
384
int decode_ping_resp(const struct nsm_msg *msg, size_t msgLen, uint8_t *cc,
385
         uint16_t *reason_code)
386
114
{
387
114
  int rc = decode_reason_code_and_cc(msg, msgLen, cc, reason_code);
388
114
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
389
58
    return rc;
390
58
  }
391
392
56
  if (msgLen <
393
56
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
394
4
    return NSM_SW_ERROR_LENGTH;
395
4
  }
396
397
52
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
398
52
  if (resp->data_size != 0) {
399
44
    return NSM_SW_ERROR_DATA;
400
44
  }
401
402
8
  return NSM_SW_SUCCESS;
403
52
}
404
405
int encode_get_supported_nvidia_message_types_req(uint8_t instance_id,
406
              struct nsm_msg *msg)
407
0
{
408
0
  if (msg == NULL) {
409
0
    return NSM_SW_ERROR_NULL;
410
0
  }
411
412
0
  struct nsm_header_info header = {0};
413
0
  header.nsm_msg_type = NSM_REQUEST;
414
0
  header.instance_id = instance_id & INSTANCEID_MASK;
415
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
416
417
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
418
0
  if (rc != NSM_SW_SUCCESS) {
419
0
    return rc;
420
0
  }
421
422
0
  struct nsm_get_supported_nvidia_message_types_req *request =
423
0
      (struct nsm_get_supported_nvidia_message_types_req *)msg->payload;
424
425
0
  request->hdr.command = NSM_SUPPORTED_NVIDIA_MESSAGE_TYPES;
426
0
  request->hdr.data_size = 0;
427
428
0
  return NSM_SW_SUCCESS;
429
0
}
430
431
int encode_get_supported_nvidia_message_types_resp(uint8_t instance_id,
432
               uint8_t cc,
433
               uint16_t reason_code,
434
               const bitfield8_t *types,
435
               struct nsm_msg *msg)
436
0
{
437
0
  if (msg == NULL) {
438
0
    return NSM_SW_ERROR_NULL;
439
0
  }
440
441
0
  struct nsm_header_info header = {0};
442
0
  header.nsm_msg_type = NSM_RESPONSE;
443
0
  header.instance_id = instance_id & INSTANCEID_MASK;
444
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
445
446
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
447
0
  if (rc != NSM_SW_SUCCESS) {
448
0
    return rc;
449
0
  }
450
451
0
  if (cc != NSM_SUCCESS) {
452
0
    return encode_reason_code(
453
0
        cc, reason_code, NSM_SUPPORTED_NVIDIA_MESSAGE_TYPES, msg);
454
0
  }
455
456
0
  struct nsm_get_supported_nvidia_message_types_resp *response =
457
0
      (struct nsm_get_supported_nvidia_message_types_resp *)msg->payload;
458
459
0
  response->hdr.command = NSM_SUPPORTED_NVIDIA_MESSAGE_TYPES;
460
0
  response->hdr.completion_code = cc;
461
0
  response->hdr.data_size = htole16(32);
462
463
0
  memcpy(response->supported_nvidia_message_types, types, 32);
464
465
0
  return NSM_SW_SUCCESS;
466
0
}
467
468
int decode_get_supported_nvidia_message_types_resp(
469
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
470
    uint16_t *reason_code, bitfield8_t types[SUPPORTED_MSG_TYPE_DATA_SIZE])
471
0
{
472
0
  if (types == NULL) {
473
0
    return NSM_SW_ERROR_NULL;
474
0
  }
475
476
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
477
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
478
0
    return rc;
479
0
  }
480
481
0
  if (msg_len <
482
0
      sizeof(struct nsm_msg_hdr) +
483
0
    sizeof(struct nsm_get_supported_nvidia_message_types_resp)) {
484
0
    return NSM_SW_ERROR_LENGTH;
485
0
  }
486
487
0
  struct nsm_get_supported_nvidia_message_types_resp *resp =
488
0
      (struct nsm_get_supported_nvidia_message_types_resp *)msg->payload;
489
490
0
  memcpy(types, resp->supported_nvidia_message_types,
491
0
         SUPPORTED_MSG_TYPE_DATA_SIZE);
492
493
0
  return NSM_SW_SUCCESS;
494
0
}
495
496
int encode_get_supported_command_codes_req(uint8_t instance_id,
497
             uint8_t nvidia_message_type,
498
             struct nsm_msg *msg)
499
0
{
500
0
  if (msg == NULL) {
501
0
    return NSM_SW_ERROR_NULL;
502
0
  }
503
504
0
  struct nsm_header_info header = {0};
505
0
  header.nsm_msg_type = NSM_REQUEST;
506
0
  header.instance_id = instance_id & INSTANCEID_MASK;
507
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
508
509
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
510
0
  if (rc != NSM_SW_SUCCESS) {
511
0
    return rc;
512
0
  }
513
514
0
  struct nsm_get_supported_command_codes_req *request =
515
0
      (struct nsm_get_supported_command_codes_req *)msg->payload;
516
517
0
  request->hdr.command = NSM_SUPPORTED_COMMAND_CODES;
518
0
  request->hdr.data_size = 1;
519
0
  request->nvidia_message_type = nvidia_message_type;
520
521
0
  return NSM_SW_SUCCESS;
522
0
}
523
524
int encode_get_supported_command_codes_resp(uint8_t instance_id, uint8_t cc,
525
              uint16_t reason_code,
526
              const bitfield8_t *command_codes,
527
              struct nsm_msg *msg)
528
0
{
529
0
  if (msg == NULL) {
530
0
    return NSM_SW_ERROR_NULL;
531
0
  }
532
533
0
  struct nsm_header_info header = {0};
534
0
  header.nsm_msg_type = NSM_RESPONSE;
535
0
  header.instance_id = instance_id & INSTANCEID_MASK;
536
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
537
538
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
539
0
  if (rc != NSM_SW_SUCCESS) {
540
0
    return rc;
541
0
  }
542
543
0
  if (cc != NSM_SUCCESS) {
544
0
    return encode_reason_code(cc, reason_code,
545
0
            NSM_SUPPORTED_COMMAND_CODES, msg);
546
0
  }
547
548
0
  struct nsm_get_supported_command_codes_resp *response =
549
0
      (struct nsm_get_supported_command_codes_resp *)msg->payload;
550
551
0
  response->hdr.command = NSM_SUPPORTED_COMMAND_CODES;
552
0
  response->hdr.completion_code = cc;
553
0
  response->hdr.data_size = htole16(32);
554
555
0
  if (command_codes == NULL) {
556
0
    return NSM_SW_ERROR_NULL;
557
0
  }
558
559
0
  memcpy(response->supported_command_codes, command_codes, 32);
560
561
0
  return NSM_SW_SUCCESS;
562
0
}
563
564
int decode_get_supported_command_codes_resp(
565
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
566
    uint16_t *reason_code,
567
    bitfield8_t command_codes[SUPPORTED_COMMAND_CODE_DATA_SIZE])
568
0
{
569
0
  if (command_codes == NULL) {
570
0
    return NSM_SW_ERROR_NULL;
571
0
  }
572
573
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
574
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
575
0
    return rc;
576
0
  }
577
578
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
579
0
        sizeof(struct nsm_get_supported_command_codes_resp)) {
580
0
    return NSM_SW_ERROR_LENGTH;
581
0
  }
582
583
0
  struct nsm_get_supported_command_codes_resp *resp =
584
0
      (struct nsm_get_supported_command_codes_resp *)msg->payload;
585
586
0
  memcpy(command_codes, resp->supported_command_codes,
587
0
         SUPPORTED_COMMAND_CODE_DATA_SIZE);
588
589
0
  return NSM_SW_SUCCESS;
590
0
}
591
592
int encode_nsm_query_device_identification_req(uint8_t instance_id,
593
                 struct nsm_msg *msg)
594
0
{
595
0
  if (msg == NULL) {
596
0
    return NSM_SW_ERROR_NULL;
597
0
  }
598
599
0
  struct nsm_header_info header = {0};
600
0
  header.nsm_msg_type = NSM_REQUEST;
601
0
  header.instance_id = instance_id & INSTANCEID_MASK;
602
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
603
604
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
605
0
  if (rc != NSM_SW_SUCCESS) {
606
0
    return rc;
607
0
  }
608
609
0
  struct nsm_query_device_identification_req *request =
610
0
      (struct nsm_query_device_identification_req *)msg->payload;
611
612
0
  request->hdr.command = NSM_QUERY_DEVICE_IDENTIFICATION;
613
0
  request->hdr.data_size = 0;
614
615
0
  return NSM_SW_SUCCESS;
616
0
}
617
618
int encode_query_device_identification_resp(uint8_t instance, uint8_t cc,
619
              uint16_t reason_code,
620
              const uint8_t device_identification,
621
              const uint8_t device_instance,
622
              struct nsm_msg *msg)
623
0
{
624
0
  if (msg == NULL) {
625
0
    return NSM_SW_ERROR_NULL;
626
0
  }
627
628
0
  struct nsm_header_info header = {0};
629
0
  header.nsm_msg_type = NSM_RESPONSE;
630
0
  header.instance_id = instance & INSTANCEID_MASK;
631
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
632
633
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
634
0
  if (rc != NSM_SW_SUCCESS) {
635
0
    return rc;
636
0
  }
637
638
0
  if (cc != NSM_SUCCESS) {
639
0
    return encode_reason_code(cc, reason_code,
640
0
            NSM_QUERY_DEVICE_IDENTIFICATION, msg);
641
0
  }
642
643
0
  struct nsm_query_device_identification_resp *response =
644
0
      (struct nsm_query_device_identification_resp *)msg->payload;
645
646
0
  response->hdr.command = NSM_QUERY_DEVICE_IDENTIFICATION;
647
0
  response->hdr.completion_code = cc;
648
0
  response->hdr.data_size = htole16(2);
649
650
0
  response->device_identification = device_identification;
651
0
  response->instance_id = device_instance;
652
653
0
  return NSM_SW_SUCCESS;
654
0
}
655
656
int decode_query_device_identification_resp(const struct nsm_msg *msg,
657
              size_t msg_len, uint8_t *cc,
658
              uint16_t *reason_code,
659
              uint8_t *device_identification,
660
              uint8_t *device_instance)
661
99
{
662
99
  if (device_identification == NULL || device_instance == NULL) {
663
0
    return NSM_SW_ERROR_NULL;
664
0
  }
665
666
99
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
667
99
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
668
57
    return rc;
669
57
  }
670
671
42
  if (msg_len < sizeof(struct nsm_msg_hdr) +
672
42
        sizeof(struct nsm_query_device_identification_resp)) {
673
5
    return NSM_SW_ERROR_LENGTH;
674
5
  }
675
676
37
  struct nsm_query_device_identification_resp *response =
677
37
      (struct nsm_query_device_identification_resp *)msg->payload;
678
679
37
  *device_identification = response->device_identification;
680
37
  *device_instance = response->instance_id;
681
682
37
  return NSM_SW_SUCCESS;
683
42
}
684
685
int encode_reason_code(uint8_t cc, uint16_t reason_code, uint8_t command_code,
686
           struct nsm_msg *msg)
687
0
{
688
0
  if (msg == NULL) {
689
0
    return NSM_SW_ERROR_NULL;
690
0
  }
691
692
0
  struct nsm_common_non_success_resp *response =
693
0
      (struct nsm_common_non_success_resp *)msg->payload;
694
695
0
  response->command = command_code;
696
0
  response->completion_code = cc;
697
0
  reason_code = htole16(reason_code);
698
0
  response->reason_code = reason_code;
699
700
0
  return NSM_SW_SUCCESS;
701
0
}
702
703
int decode_reason_code_and_cc(const struct nsm_msg *msg, size_t msg_len,
704
            uint8_t *cc, uint16_t *reason_code)
705
2.46k
{
706
2.46k
  if (msg == NULL || cc == NULL || reason_code == NULL) {
707
0
    return NSM_SW_ERROR_NULL;
708
0
  }
709
710
2.46k
  *cc = ((struct nsm_common_resp *)msg->payload)->completion_code;
711
2.46k
  if (*cc == NSM_SUCCESS || *cc == NSM_ACCEPTED) {
712
1.25k
    return NSM_SW_SUCCESS;
713
1.25k
  }
714
715
1.20k
  if (msg_len != (sizeof(struct nsm_msg_hdr) +
716
1.20k
      sizeof(struct nsm_common_non_success_resp))) {
717
1.05k
    return NSM_SW_ERROR_LENGTH;
718
1.05k
  }
719
720
148
  struct nsm_common_non_success_resp *response =
721
148
      (struct nsm_common_non_success_resp *)msg->payload;
722
723
  // reason code is expected to be present if CC != NSM_SUCCESS
724
148
  *reason_code = le16toh(response->reason_code);
725
726
148
  return NSM_SW_SUCCESS;
727
1.20k
}
728
729
int encode_nsm_event_acknowledgement(uint8_t instance_id, uint8_t nsm_type,
730
             uint8_t event_id, struct nsm_msg *msg)
731
0
{
732
0
  if (msg == NULL) {
733
0
    return NSM_ERR_INVALID_DATA;
734
0
  }
735
736
0
  struct nsm_header_info header = {0};
737
0
  header.nsm_msg_type = NSM_EVENT_ACKNOWLEDGMENT;
738
0
  header.instance_id = instance_id & 0x1f;
739
0
  header.nvidia_msg_type = nsm_type;
740
741
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
742
0
  if (rc != NSM_SUCCESS) {
743
0
    return rc;
744
0
  }
745
746
0
  struct nsm_event_ack *event = (struct nsm_event_ack *)msg->payload;
747
0
  event->event_id = event_id;
748
749
0
  return NSM_SUCCESS;
750
0
}
751
752
int decode_nsm_event_acknowledgement(const struct nsm_msg *msg, size_t msg_len,
753
             uint8_t *instance_id, uint8_t *nsm_type,
754
             uint8_t *event_id)
755
58
{
756
58
  if (msg == NULL || instance_id == NULL || nsm_type == NULL ||
757
58
      event_id == NULL) {
758
0
    return NSM_ERR_INVALID_DATA;
759
0
  }
760
761
58
  if (msg_len <
762
58
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_event_ack)) {
763
1
    return NSM_ERR_INVALID_DATA;
764
1
  }
765
766
57
  struct nsm_event_ack *event = (struct nsm_event_ack *)msg->payload;
767
768
57
  *event_id = event->event_id;
769
57
  *instance_id = msg->hdr.instance_id;
770
57
  *nsm_type = msg->hdr.nvidia_msg_type;
771
772
57
  return NSM_SUCCESS;
773
58
}
774
775
int encode_nsm_event(uint8_t instance_id, uint8_t nsm_type, bool ackr,
776
         uint8_t version, uint8_t event_id, uint8_t event_class,
777
         uint16_t event_state, uint8_t data_size, uint8_t *data,
778
         struct nsm_msg *msg)
779
0
{
780
0
  if (msg == NULL) {
781
0
    return NSM_SW_ERROR_NULL;
782
0
  }
783
784
0
  struct nsm_header_info header = {NSM_EVENT, instance_id, nsm_type};
785
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
786
0
  if (rc != NSM_SUCCESS) {
787
0
    return rc;
788
0
  }
789
790
0
  struct nsm_event *event = (struct nsm_event *)msg->payload;
791
792
0
  event->version = version;
793
0
  event->ackr = ackr;
794
0
  event->event_id = event_id;
795
0
  event->event_class = event_class;
796
0
  event->event_state = htole16(event_state);
797
0
  event->data_size = data_size;
798
0
  if (data_size > 0) {
799
0
    memcpy(event->data, data, data_size);
800
0
  }
801
802
0
  return NSM_SUCCESS;
803
0
}
804
805
int decode_nsm_event(const struct nsm_msg *msg, size_t msg_len,
806
         uint8_t event_id, uint8_t event_class,
807
         uint16_t *event_state, uint8_t *data_size)
808
245
{
809
245
  if (msg == NULL || event_state == NULL || data_size == NULL) {
810
0
    return NSM_SW_ERROR_NULL;
811
0
  }
812
813
245
  if (msg_len < sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN) {
814
10
    return NSM_SW_ERROR_LENGTH;
815
10
  }
816
817
235
  struct nsm_event *event = (struct nsm_event *)msg->payload;
818
819
235
  if (event_id != event->event_id || event_class != event->event_class) {
820
61
    return NSM_SW_ERROR_DATA;
821
61
  }
822
174
  *event_state = le16toh(event->event_state);
823
174
  *data_size = event->data_size;
824
825
174
  if (msg_len < (sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
826
174
           event->data_size)) {
827
19
    return NSM_SW_ERROR_LENGTH;
828
19
  }
829
830
155
  return NSM_SW_SUCCESS;
831
174
}
832
833
int decode_nsm_event_with_data(const struct nsm_msg *msg, size_t msg_len,
834
             uint8_t event_id, uint8_t event_class,
835
             uint16_t *event_state, uint8_t *data_size,
836
             uint8_t *data)
837
127
{
838
127
  int rc = decode_nsm_event(msg, msg_len, event_id, event_class,
839
127
          event_state, data_size);
840
127
  if (rc != NSM_SW_SUCCESS) {
841
42
    return rc;
842
42
  }
843
844
85
  struct nsm_event *event = (struct nsm_event *)msg->payload;
845
85
  if (event->data_size > 0) {
846
37
    if (data == NULL) {
847
0
      return NSM_SW_ERROR_NULL;
848
0
    }
849
37
    memcpy(data, event->data, event->data_size);
850
37
  }
851
852
85
  return NSM_SW_SUCCESS;
853
85
}
854
855
int encode_common_req(uint8_t instance_id, uint8_t nvidia_msg_type,
856
          uint8_t command, struct nsm_msg *msg)
857
0
{
858
0
  if (msg == NULL) {
859
0
    return NSM_SW_ERROR_NULL;
860
0
  }
861
862
0
  struct nsm_header_info header = {NSM_REQUEST, instance_id,
863
0
           nvidia_msg_type};
864
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
865
0
  if (rc != NSM_SW_SUCCESS) {
866
0
    return rc;
867
0
  }
868
869
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
870
871
0
  request->command = command;
872
0
  request->data_size = 0;
873
874
0
  return NSM_SW_SUCCESS;
875
0
}
876
877
int decode_common_req(const struct nsm_msg *msg, size_t msg_len)
878
1.04k
{
879
1.04k
  if (msg == NULL) {
880
0
    return NSM_SW_ERROR_NULL;
881
0
  }
882
883
1.04k
  struct nsm_header_info header = {0};
884
1.04k
  uint8_t rc = unpack_nsm_header(&msg->hdr, &header);
885
1.04k
  if (rc != NSM_SW_SUCCESS) {
886
485
    return rc;
887
485
  }
888
889
558
  if (msg_len <
890
558
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_req)) {
891
29
    return NSM_SW_ERROR_LENGTH;
892
29
  }
893
529
  return NSM_SW_SUCCESS;
894
558
}
895
896
int encode_common_resp(uint8_t instance_id, uint8_t cc, uint16_t reason_code,
897
           uint8_t nvidia_msg_type, uint8_t command,
898
           struct nsm_msg *msg)
899
0
{
900
0
  if (msg == NULL) {
901
0
    return NSM_SW_ERROR_NULL;
902
0
  }
903
904
0
  struct nsm_header_info header = {NSM_RESPONSE, instance_id,
905
0
           nvidia_msg_type};
906
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
907
0
  if (rc != NSM_SW_SUCCESS) {
908
0
    return rc;
909
0
  }
910
911
0
  if (cc != NSM_SUCCESS && cc != NSM_ACCEPTED) {
912
0
    return encode_reason_code(cc, reason_code, command, msg);
913
0
  }
914
915
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
916
917
0
  resp->command = command;
918
0
  resp->completion_code = cc;
919
0
  resp->data_size = htole16(0);
920
0
  return NSM_SW_SUCCESS;
921
0
}
922
923
int decode_common_resp(const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
924
           uint16_t *data_size, uint16_t *reason_code)
925
960
{
926
960
  if (msg == NULL || cc == NULL || data_size == NULL) {
927
0
    return NSM_SW_ERROR_NULL;
928
0
  }
929
930
960
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
931
960
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
932
437
    return rc;
933
437
  }
934
935
523
  if (msg_len <
936
523
      (sizeof(struct nsm_msg_hdr)) + sizeof(struct nsm_common_resp)) {
937
32
    return NSM_SW_ERROR_LENGTH;
938
32
  }
939
940
491
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
941
942
491
  *data_size = le16toh(resp->data_size);
943
944
491
  return NSM_SW_SUCCESS;
945
523
}
946
947
/** @brief Encode a long running event state
948
 *
949
 *  @param[in] event_state - long running event state
950
 *  @return uint16_t - Encoded long running event state
951
 */
952
static uint16_t encode_long_running_event_state(
953
    const struct nsm_long_running_event_state *event_state)
954
104
{
955
104
  if (event_state == NULL) {
956
0
    return 0;
957
0
  }
958
104
  return *(uint16_t *)event_state;
959
104
}
960
961
int encode_long_running_resp(uint8_t instance_id, uint8_t cc,
962
           uint16_t reason_code, uint8_t nvidia_msg_type,
963
           uint8_t command, const uint8_t *data,
964
           uint8_t data_size, struct nsm_msg *msg)
965
0
{
966
0
  struct nsm_long_running_event_state event_state = {
967
0
      .nvidia_message_type = nvidia_msg_type, .command = command};
968
0
  int rc = encode_nsm_event(
969
0
      instance_id, NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY, false,
970
0
      NSM_EVENT_VERSION, NSM_LONG_RUNNING_EVENT,
971
0
      NSM_NVIDIA_GENERAL_EVENT_CLASS,
972
0
      encode_long_running_event_state(&event_state), 0, NULL, msg);
973
0
  if (rc != NSM_SW_SUCCESS) {
974
0
    return rc;
975
0
  }
976
977
0
  struct nsm_event *event = (struct nsm_event *)msg->payload;
978
0
  if (cc != NSM_SUCCESS) {
979
0
    struct nsm_long_running_non_success_resp *resp =
980
0
        (struct nsm_long_running_non_success_resp *)event->data;
981
982
0
    event->data_size =
983
0
        sizeof(struct nsm_long_running_non_success_resp);
984
0
    resp->completion_code = cc;
985
0
    resp->reason_code = htole16(reason_code);
986
0
    resp->instance_id = instance_id;
987
988
0
    rc = NSM_SW_SUCCESS;
989
0
  } else {
990
0
    struct nsm_long_running_resp *resp =
991
0
        (struct nsm_long_running_resp *)event->data;
992
0
    resp->completion_code = cc;
993
0
    resp->reserved = 0;
994
0
    resp->instance_id = instance_id;
995
996
0
    if (data_size >
997
0
        (UCHAR_MAX - sizeof(struct nsm_long_running_resp))) {
998
0
      rc = NSM_SW_ERROR_LENGTH;
999
0
    } else if (data_size > 0 && data == NULL) {
1000
0
      rc = NSM_SW_ERROR_NULL;
1001
0
    } else {
1002
0
      event->data_size =
1003
0
          data_size + sizeof(struct nsm_long_running_resp);
1004
0
      if (data != NULL) {
1005
0
        memcpy(event->data +
1006
0
             sizeof(struct nsm_long_running_resp),
1007
0
               data, data_size);
1008
0
      }
1009
0
      rc = NSM_SW_SUCCESS;
1010
0
    }
1011
0
  }
1012
0
  return rc;
1013
0
}
1014
1015
int decode_long_running_event(const struct nsm_msg *msg, size_t msg_len,
1016
            uint8_t *instance_id, uint8_t *cc,
1017
            uint16_t *reason_code)
1018
360
{
1019
360
  if (msg == NULL) {
1020
0
    return NSM_SW_ERROR_NULL;
1021
0
  }
1022
1023
360
  if (msg_len < sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
1024
360
        sizeof(struct nsm_long_running_resp)) {
1025
19
    return NSM_SW_ERROR_LENGTH;
1026
19
  }
1027
1028
341
  struct nsm_event *event = (struct nsm_event *)msg->payload;
1029
341
  event->event_state = le16toh(event->event_state);
1030
1031
341
  if (instance_id != NULL) {
1032
60
    *instance_id =
1033
60
        ((struct nsm_long_running_resp *)event->data)->instance_id;
1034
60
  }
1035
341
  if (cc != NULL && reason_code != NULL) {
1036
341
    *cc = ((struct nsm_long_running_resp *)event->data)
1037
341
        ->completion_code;
1038
341
    if (*cc != NSM_SUCCESS) {
1039
158
      if (msg_len !=
1040
158
          (sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
1041
158
           sizeof(
1042
158
         struct nsm_long_running_non_success_resp))) {
1043
131
        return NSM_SW_ERROR_LENGTH;
1044
131
      }
1045
1046
27
      struct nsm_long_running_non_success_resp *response =
1047
27
          (struct nsm_long_running_non_success_resp *)
1048
27
        event->data;
1049
1050
      // reason code is expected to be present if CC !=
1051
      // NSM_SUCCESS
1052
27
      *reason_code = le16toh(response->reason_code);
1053
27
    }
1054
341
  }
1055
210
  return NSM_SW_SUCCESS;
1056
341
}
1057
1058
int decode_long_running_resp(const struct nsm_msg *msg, size_t msg_len,
1059
           uint8_t nvidia_msg_type, uint8_t command,
1060
           uint8_t *cc, uint16_t *reason_code)
1061
294
{
1062
294
  if (cc == NULL || reason_code == NULL) {
1063
0
    return NSM_SW_ERROR_NULL;
1064
0
  }
1065
1066
294
  int rc = decode_long_running_event(msg, msg_len, NULL, cc, reason_code);
1067
294
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1068
117
    return rc;
1069
117
  }
1070
1071
177
  struct nsm_event *event = (struct nsm_event *)msg->payload;
1072
177
  struct nsm_long_running_event_state event_state = {
1073
177
      .nvidia_message_type = nvidia_msg_type, .command = command};
1074
1075
177
  if (msg->hdr.nvidia_msg_type != NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY ||
1076
154
      event->event_class != NSM_NVIDIA_GENERAL_EVENT_CLASS ||
1077
121
      event->event_id != NSM_LONG_RUNNING_EVENT ||
1078
104
      event->event_state !=
1079
123
    encode_long_running_event_state(&event_state)) {
1080
123
    return NSM_SW_ERROR_DATA;
1081
123
  }
1082
1083
54
  return NSM_SW_SUCCESS;
1084
177
}
1085
1086
int decode_long_running_resp_with_data(const struct nsm_msg *msg,
1087
               size_t msg_len, uint8_t nvidia_msg_type,
1088
               uint8_t command, uint8_t *cc,
1089
               uint16_t *reason_code, uint8_t *data,
1090
               uint8_t data_size)
1091
174
{
1092
174
  int rc = decode_long_running_resp(msg, msg_len, nvidia_msg_type,
1093
174
            command, cc, reason_code);
1094
174
  if (rc != NSM_SW_SUCCESS) {
1095
110
    return rc;
1096
110
  }
1097
1098
64
  if (data == NULL) {
1099
0
    return NSM_SW_ERROR_NULL;
1100
0
  }
1101
1102
64
  struct nsm_event *event = (struct nsm_event *)msg->payload;
1103
64
  if (msg_len < (sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
1104
64
           event->data_size) ||
1105
56
      event->data_size < sizeof(struct nsm_long_running_resp) ||
1106
33
      (event->data_size - sizeof(struct nsm_long_running_resp)) <
1107
33
    data_size) {
1108
31
    return NSM_SW_ERROR_LENGTH;
1109
31
  }
1110
33
  memcpy(data, event->data + sizeof(struct nsm_long_running_resp),
1111
33
         event->data_size - sizeof(struct nsm_long_running_resp));
1112
1113
33
  return NSM_SW_SUCCESS;
1114
64
}
1115
1116
int encode_raw_cmd_req(uint8_t instanceId, uint8_t messageType,
1117
           uint8_t commandCode, const uint8_t *payload,
1118
           size_t dataSize, struct nsm_msg *msg)
1119
0
{
1120
0
  if (!msg || (dataSize > 0 && !payload)) {
1121
0
    return NSM_SW_ERROR_NULL;
1122
0
  }
1123
1124
  // Reuse encode_common_req for setting up the header and command
1125
  // structure
1126
0
  uint8_t rc =
1127
0
      encode_common_req(instanceId, messageType, commandCode, msg);
1128
0
  if (rc != NSM_SW_SUCCESS) {
1129
0
    return rc;
1130
0
  }
1131
1132
  // Copy the command data into the payload after the common request
1133
0
  if (dataSize > 0) {
1134
0
    memcpy(msg->payload + sizeof(struct nsm_common_req), payload,
1135
0
           dataSize);
1136
0
  }
1137
1138
  // Set the data_size to the size of the command data
1139
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
1140
0
  request->data_size = dataSize;
1141
1142
0
  return NSM_SW_SUCCESS;
1143
0
}
1144
1145
int encode_get_histogram_format_req(uint8_t instance_id, uint32_t histogram_id,
1146
            uint16_t parameter, struct nsm_msg *msg)
1147
0
{
1148
0
  if (msg == NULL) {
1149
0
    return NSM_SW_ERROR_NULL;
1150
0
  }
1151
1152
0
  struct nsm_header_info header = {0};
1153
0
  header.nsm_msg_type = NSM_REQUEST;
1154
0
  header.instance_id = instance_id;
1155
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
1156
1157
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
1158
0
  if (rc != NSM_SW_SUCCESS) {
1159
0
    return rc;
1160
0
  }
1161
1162
0
  struct nsm_get_histogram_format_req *request =
1163
0
      (struct nsm_get_histogram_format_req *)msg->payload;
1164
1165
0
  request->hdr.command = NSM_GET_HISTOGRAM_FORMAT;
1166
0
  request->hdr.data_size = sizeof(histogram_id) + sizeof(parameter);
1167
0
  request->histogram_id = htole32(histogram_id);
1168
0
  request->parameter = htole16(parameter);
1169
1170
0
  return NSM_SW_SUCCESS;
1171
0
}
1172
1173
int decode_get_histogram_format_req(const struct nsm_msg *msg, size_t msg_len,
1174
            uint32_t *histogram_id, uint16_t *parameter)
1175
66
{
1176
66
  if (msg == NULL || histogram_id == NULL || parameter == NULL) {
1177
0
    return NSM_SW_ERROR_NULL;
1178
0
  }
1179
1180
66
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1181
66
        sizeof(struct nsm_get_histogram_format_req)) {
1182
6
    return NSM_SW_ERROR_LENGTH;
1183
6
  }
1184
1185
60
  struct nsm_get_histogram_format_req *request =
1186
60
      (struct nsm_get_histogram_format_req *)msg->payload;
1187
1188
60
  if (request->hdr.data_size <
1189
60
      sizeof(request->histogram_id) + sizeof(request->parameter)) {
1190
10
    return NSM_SW_ERROR_DATA;
1191
10
  }
1192
1193
50
  *histogram_id = le32toh(request->histogram_id);
1194
50
  *parameter = le16toh(request->parameter);
1195
1196
50
  return NSM_SW_SUCCESS;
1197
60
}
1198
1199
int encode_get_histogram_format_resp(
1200
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
1201
    struct nsm_histogram_format_metadata *meta_data, uint8_t *bucket_offsets,
1202
    uint32_t bucket_offsets_size, struct nsm_msg *msg)
1203
0
{
1204
0
  if (msg == NULL) {
1205
0
    return NSM_SW_ERROR_NULL;
1206
0
  }
1207
1208
0
  struct nsm_header_info header = {0};
1209
0
  header.nsm_msg_type = NSM_RESPONSE;
1210
0
  header.instance_id = instance_id & INSTANCEID_MASK;
1211
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
1212
1213
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1214
0
  if (rc != NSM_SW_SUCCESS) {
1215
0
    return rc;
1216
0
  }
1217
1218
0
  if (cc != NSM_SUCCESS) {
1219
0
    return encode_reason_code(cc, reason_code,
1220
0
            NSM_GET_HISTOGRAM_FORMAT, msg);
1221
0
  }
1222
1223
0
  struct nsm_get_histogram_format_resp *resp =
1224
0
      (struct nsm_get_histogram_format_resp *)msg->payload;
1225
1226
0
  resp->hdr.command = NSM_GET_HISTOGRAM_FORMAT;
1227
0
  resp->hdr.completion_code = cc;
1228
0
  resp->hdr.data_size = htole16(
1229
0
      sizeof(struct nsm_histogram_format_metadata) + bucket_offsets_size);
1230
0
  resp->metadata.num_of_buckets = htole16(meta_data->num_of_buckets);
1231
0
  resp->metadata.min_sampling_time =
1232
0
      htole32(meta_data->min_sampling_time);
1233
0
  resp->metadata.accumulation_cycle = meta_data->accumulation_cycle;
1234
0
  resp->metadata.reserved0 = 0;
1235
0
  resp->metadata.increment_duration =
1236
0
      htole32(meta_data->increment_duration);
1237
0
  resp->metadata.bucket_unit_of_measure =
1238
0
      meta_data->bucket_unit_of_measure;
1239
0
  resp->metadata.reserved1 = 0;
1240
0
  resp->metadata.bucket_data_type = meta_data->bucket_data_type;
1241
0
  resp->metadata.reserved2 = 0;
1242
1243
0
  if (cc == NSM_SUCCESS) {
1244
0
    if (bucket_offsets == NULL) {
1245
0
      return NSM_SW_ERROR_NULL;
1246
0
    }
1247
1248
0
    htoleArrayData(bucket_offsets, meta_data->num_of_buckets,
1249
0
             meta_data->bucket_data_type);
1250
0
    dataCopy(bucket_offsets, resp->bucket_offsets,
1251
0
       meta_data->num_of_buckets,
1252
0
       meta_data->bucket_data_type);
1253
0
  }
1254
1255
0
  return NSM_SW_SUCCESS;
1256
0
}
1257
1258
int decode_get_histogram_format_resp(
1259
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
1260
    uint16_t *reason_code, uint16_t *data_size,
1261
    struct nsm_histogram_format_metadata *meta_data, uint8_t *bucket_offsets,
1262
    uint32_t *bucket_offsets_size)
1263
127
{
1264
127
  if (data_size == NULL || meta_data == NULL || bucket_offsets == NULL ||
1265
127
      bucket_offsets_size == NULL) {
1266
0
    return NSM_SW_ERROR_NULL;
1267
0
  }
1268
1269
127
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1270
127
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1271
58
    return rc;
1272
58
  }
1273
1274
69
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1275
69
        sizeof(struct nsm_get_histogram_format_resp)) {
1276
8
    return NSM_SW_ERROR_LENGTH;
1277
8
  }
1278
1279
61
  struct nsm_get_histogram_format_resp *resp =
1280
61
      (struct nsm_get_histogram_format_resp *)msg->payload;
1281
1282
61
  *data_size = le16toh(resp->hdr.data_size);
1283
61
  meta_data->num_of_buckets = le16toh(resp->metadata.num_of_buckets);
1284
61
  meta_data->min_sampling_time =
1285
61
      le32toh(resp->metadata.min_sampling_time);
1286
61
  meta_data->accumulation_cycle = resp->metadata.accumulation_cycle;
1287
61
  meta_data->reserved0 = 0;
1288
61
  meta_data->increment_duration =
1289
61
      le32toh(resp->metadata.increment_duration);
1290
61
  meta_data->bucket_unit_of_measure =
1291
61
      resp->metadata.bucket_unit_of_measure;
1292
61
  meta_data->reserved1 = 0;
1293
61
  meta_data->bucket_data_type = resp->metadata.bucket_data_type;
1294
61
  meta_data->reserved2 = 0;
1295
61
  *bucket_offsets_size =
1296
61
      *data_size - sizeof(struct nsm_histogram_format_metadata);
1297
1298
61
  dataCopy(resp->bucket_offsets, bucket_offsets,
1299
61
     meta_data->num_of_buckets, meta_data->bucket_data_type);
1300
61
  letohArrayData(bucket_offsets, meta_data->num_of_buckets,
1301
61
           meta_data->bucket_data_type);
1302
1303
61
  return NSM_SW_SUCCESS;
1304
69
}
1305
1306
int encode_get_histogram_data_req(uint8_t instance_id, uint32_t histogram_id,
1307
          uint16_t parameter, struct nsm_msg *msg)
1308
0
{
1309
0
  if (msg == NULL) {
1310
0
    return NSM_SW_ERROR_NULL;
1311
0
  }
1312
1313
0
  struct nsm_header_info header = {0};
1314
0
  header.nsm_msg_type = NSM_REQUEST;
1315
0
  header.instance_id = instance_id;
1316
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
1317
1318
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
1319
0
  if (rc != NSM_SW_SUCCESS) {
1320
0
    return rc;
1321
0
  }
1322
1323
0
  nsm_get_histogram_data_req *request =
1324
0
      (nsm_get_histogram_data_req *)msg->payload;
1325
1326
0
  request->hdr.command = NSM_GET_HISTOGRAM_DATA;
1327
0
  request->hdr.data_size = sizeof(histogram_id) + sizeof(parameter);
1328
0
  request->histogram_id = htole32(histogram_id);
1329
0
  request->parameter = htole16(parameter);
1330
1331
0
  return NSM_SW_SUCCESS;
1332
0
}
1333
1334
int decode_get_histogram_data_req(const struct nsm_msg *msg, size_t msg_len,
1335
          uint32_t *histogram_id, uint16_t *parameter)
1336
60
{
1337
60
  if (msg == NULL || histogram_id == NULL || parameter == NULL) {
1338
0
    return NSM_SW_ERROR_NULL;
1339
0
  }
1340
1341
60
  if (msg_len <
1342
60
      sizeof(struct nsm_msg_hdr) + sizeof(nsm_get_histogram_data_req)) {
1343
6
    return NSM_SW_ERROR_LENGTH;
1344
6
  }
1345
1346
54
  nsm_get_histogram_data_req *request =
1347
54
      (nsm_get_histogram_data_req *)msg->payload;
1348
1349
54
  if (request->hdr.data_size <
1350
54
      sizeof(request->histogram_id) + sizeof(request->parameter)) {
1351
37
    return NSM_SW_ERROR_DATA;
1352
37
  }
1353
1354
17
  *histogram_id = le32toh(request->histogram_id);
1355
17
  *parameter = le16toh(request->parameter);
1356
1357
17
  return NSM_SW_SUCCESS;
1358
54
}
1359
1360
int encode_get_histogram_data_resp(
1361
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
1362
    uint8_t bucket_data_type, uint16_t num_of_buckets, uint8_t *bucket_data,
1363
    uint32_t bucket_data_size, struct nsm_msg *msg)
1364
0
{
1365
0
  if (msg == NULL) {
1366
0
    return NSM_SW_ERROR_NULL;
1367
0
  }
1368
1369
0
  struct nsm_header_info header = {0};
1370
0
  header.nsm_msg_type = NSM_RESPONSE;
1371
0
  header.instance_id = instance_id & INSTANCEID_MASK;
1372
0
  header.nvidia_msg_type = NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY;
1373
1374
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1375
0
  if (rc != NSM_SW_SUCCESS) {
1376
0
    return rc;
1377
0
  }
1378
1379
0
  if (cc != NSM_SUCCESS) {
1380
0
    return encode_reason_code(cc, reason_code,
1381
0
            NSM_GET_HISTOGRAM_DATA, msg);
1382
0
  }
1383
1384
0
  struct nsm_get_histogram_data_resp *resp =
1385
0
      (struct nsm_get_histogram_data_resp *)msg->payload;
1386
1387
0
  resp->hdr.command = NSM_GET_HISTOGRAM_DATA;
1388
0
  resp->hdr.completion_code = cc;
1389
0
  resp->hdr.data_size =
1390
0
      htole16(sizeof(num_of_buckets) + sizeof(bucket_data_type) +
1391
0
        bucket_data_size);
1392
0
  resp->bucket_data_type = bucket_data_type;
1393
0
  resp->num_of_buckets = htole16(num_of_buckets);
1394
1395
0
  if (cc == NSM_SUCCESS) {
1396
0
    if (bucket_data == NULL) {
1397
0
      return NSM_SW_ERROR_NULL;
1398
0
    }
1399
1400
0
    htoleArrayData(bucket_data, num_of_buckets, bucket_data_type);
1401
0
    dataCopy(bucket_data, resp->bucket_data, num_of_buckets,
1402
0
       bucket_data_type);
1403
0
  }
1404
1405
0
  return NSM_SW_SUCCESS;
1406
0
}
1407
1408
int decode_get_histogram_data_resp(
1409
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
1410
    uint16_t *reason_code, uint16_t *data_size, uint8_t *bucket_data_type,
1411
    uint16_t *num_of_buckets, uint8_t *bucket_data, uint32_t *bucket_data_size)
1412
125
{
1413
125
  if (data_size == NULL || bucket_data_type == NULL ||
1414
125
      num_of_buckets == NULL || bucket_data == NULL ||
1415
125
      bucket_data_size == NULL) {
1416
0
    return NSM_SW_ERROR_NULL;
1417
0
  }
1418
1419
125
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1420
125
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1421
59
    return rc;
1422
59
  }
1423
1424
66
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1425
66
        sizeof(struct nsm_get_histogram_data_resp)) {
1426
6
    return NSM_SW_ERROR_LENGTH;
1427
6
  }
1428
1429
60
  struct nsm_get_histogram_data_resp *resp =
1430
60
      (struct nsm_get_histogram_data_resp *)msg->payload;
1431
1432
60
  *data_size = le16toh(resp->hdr.data_size);
1433
60
  *bucket_data_type = resp->bucket_data_type;
1434
60
  *num_of_buckets = le16toh(resp->num_of_buckets);
1435
60
  *bucket_data_size = *data_size - sizeof(resp->num_of_buckets) -
1436
60
          sizeof(resp->bucket_data_type);
1437
1438
60
  dataCopy(resp->bucket_data, bucket_data, *num_of_buckets,
1439
60
     *bucket_data_type);
1440
60
  letohArrayData(bucket_data, *num_of_buckets, *bucket_data_type);
1441
1442
60
  return NSM_SW_SUCCESS;
1443
66
}