Coverage Report

Created: 2026-07-16 06:24

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
0
{
78
0
  if (msg == NULL || hdr == NULL) {
79
0
    return NSM_SW_ERROR_NULL;
80
0
  }
81
82
0
  if (be16toh(msg->pci_vendor_id) != PCI_VENDOR_ID) {
83
0
    return NSM_SW_ERROR_DATA;
84
0
  }
85
86
0
  if (msg->ocp_type != OCP_TYPE) {
87
0
    return NSM_SW_ERROR_DATA;
88
0
  }
89
90
0
  if (msg->ocp_version != OCP_VERSION &&
91
0
      msg->ocp_version != OCP_VERSION_V2) {
92
0
    return NSM_SW_ERROR_DATA;
93
0
  }
94
95
0
  if (msg->request == 0) {
96
0
    hdr->nsm_msg_type =
97
0
        msg->datagram ? NSM_EVENT_ACKNOWLEDGMENT : NSM_RESPONSE;
98
0
  } else {
99
0
    hdr->nsm_msg_type = msg->datagram ? NSM_EVENT : NSM_REQUEST;
100
0
  }
101
102
0
  hdr->instance_id = msg->instance_id;
103
0
  hdr->nvidia_msg_type = msg->nvidia_msg_type;
104
105
0
  return NSM_SW_SUCCESS;
106
0
}
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
0
{
198
0
  switch (data_type) {
199
0
  case NvU8:
200
0
  case NvS8:
201
    // No operation for 8-bit types, just return
202
0
    break;
203
204
0
  case NvU16: {
205
0
    uint16_t tmp = 0;
206
0
    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
0
  } break;
214
0
  case NvS16: {
215
0
    int16_t tmp = 0;
216
0
    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
0
  } break;
224
225
0
  case NvU32: {
226
0
    uint32_t tmp = 0;
227
0
    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
0
  } break;
235
0
  case NvS32: {
236
0
    int32_t tmp = 0;
237
0
    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
0
  } break;
245
246
0
  case NvS24_8: {
247
0
    float tmp = 0;
248
0
    for (size_t i = 0; i < num_of_element; ++i) {
249
0
      memcpy(&tmp, data + (i * sizeof(float)), sizeof(float));
250
0
      tmp = le32toh(tmp);
251
0
      memcpy(data + (i * sizeof(float)), &tmp, sizeof(float));
252
0
    }
253
0
  } break;
254
255
0
  case NvU64: {
256
0
    uint64_t tmp = 0;
257
0
    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
0
  } break;
265
0
  case NvS64: {
266
0
    int64_t tmp = 0;
267
0
    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
0
  } break;
275
276
0
  default:
277
    // No operation for unknown types
278
0
    break;
279
0
  }
280
0
}
281
282
static void dataCopy(uint8_t *srcData, uint8_t *destData, uint16_t numOfElement,
283
         uint8_t dataType)
284
0
{
285
0
  size_t dataSize = 0;
286
0
  switch (dataType) {
287
0
  case NvU8:
288
0
    dataSize = sizeof(uint8_t) * numOfElement;
289
0
    break;
290
0
  case NvS8:
291
0
    dataSize = sizeof(int8_t) * numOfElement;
292
0
    break;
293
0
  case NvU16:
294
0
    dataSize = sizeof(uint16_t) * numOfElement;
295
0
    break;
296
0
  case NvS16:
297
0
    dataSize = sizeof(int16_t) * numOfElement;
298
0
    break;
299
0
  case NvU32:
300
0
    dataSize = sizeof(uint32_t) * numOfElement;
301
0
    break;
302
0
  case NvS32:
303
0
    dataSize = sizeof(int32_t) * numOfElement;
304
0
    break;
305
0
  case NvS24_8:
306
0
    dataSize = sizeof(float) * numOfElement;
307
0
    break;
308
0
  case NvU64:
309
0
    dataSize = sizeof(uint64_t) * numOfElement;
310
0
    break;
311
0
  case NvS64:
312
0
    dataSize = sizeof(int64_t) * numOfElement;
313
0
    break;
314
0
  default:
315
    // No operation for 8-bit types
316
0
    break;
317
0
  }
318
0
  memcpy(destData, srcData, dataSize);
319
0
}
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
0
{
387
0
  int rc = decode_reason_code_and_cc(msg, msgLen, cc, reason_code);
388
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
389
0
    return rc;
390
0
  }
391
392
0
  if (msgLen <
393
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
394
0
    return NSM_SW_ERROR_LENGTH;
395
0
  }
396
397
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
398
0
  if (resp->data_size != 0) {
399
0
    return NSM_SW_ERROR_DATA;
400
0
  }
401
402
0
  return NSM_SW_SUCCESS;
403
0
}
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
0
{
662
0
  if (device_identification == NULL || device_instance == NULL) {
663
0
    return NSM_SW_ERROR_NULL;
664
0
  }
665
666
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
667
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
668
0
    return rc;
669
0
  }
670
671
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
672
0
        sizeof(struct nsm_query_device_identification_resp)) {
673
0
    return NSM_SW_ERROR_LENGTH;
674
0
  }
675
676
0
  struct nsm_query_device_identification_resp *response =
677
0
      (struct nsm_query_device_identification_resp *)msg->payload;
678
679
0
  *device_identification = response->device_identification;
680
0
  *device_instance = response->instance_id;
681
682
0
  return NSM_SW_SUCCESS;
683
0
}
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
93
{
706
93
  if (msg == NULL || cc == NULL || reason_code == NULL) {
707
0
    return NSM_SW_ERROR_NULL;
708
0
  }
709
710
93
  *cc = ((struct nsm_common_resp *)msg->payload)->completion_code;
711
93
  if (*cc == NSM_SUCCESS || *cc == NSM_ACCEPTED) {
712
44
    return NSM_SW_SUCCESS;
713
44
  }
714
715
49
  if (msg_len != (sizeof(struct nsm_msg_hdr) +
716
49
      sizeof(struct nsm_common_non_success_resp))) {
717
42
    return NSM_SW_ERROR_LENGTH;
718
42
  }
719
720
7
  struct nsm_common_non_success_resp *response =
721
7
      (struct nsm_common_non_success_resp *)msg->payload;
722
723
  // reason code is expected to be present if CC != NSM_SUCCESS
724
7
  *reason_code = le16toh(response->reason_code);
725
726
7
  return NSM_SW_SUCCESS;
727
49
}
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
0
{
756
0
  if (msg == NULL || instance_id == NULL || nsm_type == NULL ||
757
0
      event_id == NULL) {
758
0
    return NSM_ERR_INVALID_DATA;
759
0
  }
760
761
0
  if (msg_len <
762
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_event_ack)) {
763
0
    return NSM_ERR_INVALID_DATA;
764
0
  }
765
766
0
  struct nsm_event_ack *event = (struct nsm_event_ack *)msg->payload;
767
768
0
  *event_id = event->event_id;
769
0
  *instance_id = msg->hdr.instance_id;
770
0
  *nsm_type = msg->hdr.nvidia_msg_type;
771
772
0
  return NSM_SUCCESS;
773
0
}
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
0
{
809
0
  if (msg == NULL || event_state == NULL || data_size == NULL) {
810
0
    return NSM_SW_ERROR_NULL;
811
0
  }
812
813
0
  if (msg_len < sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN) {
814
0
    return NSM_SW_ERROR_LENGTH;
815
0
  }
816
817
0
  struct nsm_event *event = (struct nsm_event *)msg->payload;
818
819
0
  if (event_id != event->event_id || event_class != event->event_class) {
820
0
    return NSM_SW_ERROR_DATA;
821
0
  }
822
0
  *event_state = le16toh(event->event_state);
823
0
  *data_size = event->data_size;
824
825
0
  if (msg_len < (sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
826
0
           event->data_size)) {
827
0
    return NSM_SW_ERROR_LENGTH;
828
0
  }
829
830
0
  return NSM_SW_SUCCESS;
831
0
}
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
0
{
838
0
  int rc = decode_nsm_event(msg, msg_len, event_id, event_class,
839
0
          event_state, data_size);
840
0
  if (rc != NSM_SW_SUCCESS) {
841
0
    return rc;
842
0
  }
843
844
0
  struct nsm_event *event = (struct nsm_event *)msg->payload;
845
0
  if (event->data_size > 0) {
846
0
    if (data == NULL) {
847
0
      return NSM_SW_ERROR_NULL;
848
0
    }
849
0
    memcpy(data, event->data, event->data_size);
850
0
  }
851
852
0
  return NSM_SW_SUCCESS;
853
0
}
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
0
{
879
0
  if (msg == NULL) {
880
0
    return NSM_SW_ERROR_NULL;
881
0
  }
882
883
0
  struct nsm_header_info header = {0};
884
0
  uint8_t rc = unpack_nsm_header(&msg->hdr, &header);
885
0
  if (rc != NSM_SW_SUCCESS) {
886
0
    return rc;
887
0
  }
888
889
0
  if (msg_len <
890
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_req)) {
891
0
    return NSM_SW_ERROR_LENGTH;
892
0
  }
893
0
  return NSM_SW_SUCCESS;
894
0
}
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
93
{
926
93
  if (msg == NULL || cc == NULL || data_size == NULL) {
927
0
    return NSM_SW_ERROR_NULL;
928
0
  }
929
930
93
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
931
93
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
932
50
    return rc;
933
50
  }
934
935
43
  if (msg_len <
936
43
      (sizeof(struct nsm_msg_hdr)) + sizeof(struct nsm_common_resp)) {
937
4
    return NSM_SW_ERROR_LENGTH;
938
4
  }
939
940
39
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
941
942
39
  *data_size = le16toh(resp->data_size);
943
944
39
  return NSM_SW_SUCCESS;
945
43
}
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
0
{
955
0
  if (event_state == NULL) {
956
0
    return 0;
957
0
  }
958
0
  return *(uint16_t *)event_state;
959
0
}
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
0
{
1019
0
  if (msg == NULL) {
1020
0
    return NSM_SW_ERROR_NULL;
1021
0
  }
1022
1023
0
  if (msg_len < sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
1024
0
        sizeof(struct nsm_long_running_resp)) {
1025
0
    return NSM_SW_ERROR_LENGTH;
1026
0
  }
1027
1028
0
  struct nsm_event *event = (struct nsm_event *)msg->payload;
1029
0
  event->event_state = le16toh(event->event_state);
1030
1031
0
  if (instance_id != NULL) {
1032
0
    *instance_id =
1033
0
        ((struct nsm_long_running_resp *)event->data)->instance_id;
1034
0
  }
1035
0
  if (cc != NULL && reason_code != NULL) {
1036
0
    *cc = ((struct nsm_long_running_resp *)event->data)
1037
0
        ->completion_code;
1038
0
    if (*cc != NSM_SUCCESS) {
1039
0
      if (msg_len !=
1040
0
          (sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
1041
0
           sizeof(
1042
0
         struct nsm_long_running_non_success_resp))) {
1043
0
        return NSM_SW_ERROR_LENGTH;
1044
0
      }
1045
1046
0
      struct nsm_long_running_non_success_resp *response =
1047
0
          (struct nsm_long_running_non_success_resp *)
1048
0
        event->data;
1049
1050
      // reason code is expected to be present if CC !=
1051
      // NSM_SUCCESS
1052
0
      *reason_code = le16toh(response->reason_code);
1053
0
    }
1054
0
  }
1055
0
  return NSM_SW_SUCCESS;
1056
0
}
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
0
{
1062
0
  if (cc == NULL || reason_code == NULL) {
1063
0
    return NSM_SW_ERROR_NULL;
1064
0
  }
1065
1066
0
  int rc = decode_long_running_event(msg, msg_len, NULL, cc, reason_code);
1067
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1068
0
    return rc;
1069
0
  }
1070
1071
0
  struct nsm_event *event = (struct nsm_event *)msg->payload;
1072
0
  struct nsm_long_running_event_state event_state = {
1073
0
      .nvidia_message_type = nvidia_msg_type, .command = command};
1074
1075
0
  if (msg->hdr.nvidia_msg_type != NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY ||
1076
0
      event->event_class != NSM_NVIDIA_GENERAL_EVENT_CLASS ||
1077
0
      event->event_id != NSM_LONG_RUNNING_EVENT ||
1078
0
      event->event_state !=
1079
0
    encode_long_running_event_state(&event_state)) {
1080
0
    return NSM_SW_ERROR_DATA;
1081
0
  }
1082
1083
0
  return NSM_SW_SUCCESS;
1084
0
}
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
0
{
1092
0
  int rc = decode_long_running_resp(msg, msg_len, nvidia_msg_type,
1093
0
            command, cc, reason_code);
1094
0
  if (rc != NSM_SW_SUCCESS) {
1095
0
    return rc;
1096
0
  }
1097
1098
0
  if (data == NULL) {
1099
0
    return NSM_SW_ERROR_NULL;
1100
0
  }
1101
1102
0
  struct nsm_event *event = (struct nsm_event *)msg->payload;
1103
0
  if (msg_len < (sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
1104
0
           event->data_size) ||
1105
0
      event->data_size < sizeof(struct nsm_long_running_resp) ||
1106
0
      (event->data_size - sizeof(struct nsm_long_running_resp)) <
1107
0
    data_size) {
1108
0
    return NSM_SW_ERROR_LENGTH;
1109
0
  }
1110
0
  memcpy(data, event->data + sizeof(struct nsm_long_running_resp),
1111
0
         event->data_size - sizeof(struct nsm_long_running_resp));
1112
1113
0
  return NSM_SW_SUCCESS;
1114
0
}
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
0
{
1176
0
  if (msg == NULL || histogram_id == NULL || parameter == NULL) {
1177
0
    return NSM_SW_ERROR_NULL;
1178
0
  }
1179
1180
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1181
0
        sizeof(struct nsm_get_histogram_format_req)) {
1182
0
    return NSM_SW_ERROR_LENGTH;
1183
0
  }
1184
1185
0
  struct nsm_get_histogram_format_req *request =
1186
0
      (struct nsm_get_histogram_format_req *)msg->payload;
1187
1188
0
  if (request->hdr.data_size <
1189
0
      sizeof(request->histogram_id) + sizeof(request->parameter)) {
1190
0
    return NSM_SW_ERROR_DATA;
1191
0
  }
1192
1193
0
  *histogram_id = le32toh(request->histogram_id);
1194
0
  *parameter = le16toh(request->parameter);
1195
1196
0
  return NSM_SW_SUCCESS;
1197
0
}
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
0
{
1264
0
  if (data_size == NULL || meta_data == NULL || bucket_offsets == NULL ||
1265
0
      bucket_offsets_size == NULL) {
1266
0
    return NSM_SW_ERROR_NULL;
1267
0
  }
1268
1269
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1270
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1271
0
    return rc;
1272
0
  }
1273
1274
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1275
0
        sizeof(struct nsm_get_histogram_format_resp)) {
1276
0
    return NSM_SW_ERROR_LENGTH;
1277
0
  }
1278
1279
0
  struct nsm_get_histogram_format_resp *resp =
1280
0
      (struct nsm_get_histogram_format_resp *)msg->payload;
1281
1282
0
  *data_size = le16toh(resp->hdr.data_size);
1283
0
  meta_data->num_of_buckets = le16toh(resp->metadata.num_of_buckets);
1284
0
  meta_data->min_sampling_time =
1285
0
      le32toh(resp->metadata.min_sampling_time);
1286
0
  meta_data->accumulation_cycle = resp->metadata.accumulation_cycle;
1287
0
  meta_data->reserved0 = 0;
1288
0
  meta_data->increment_duration =
1289
0
      le32toh(resp->metadata.increment_duration);
1290
0
  meta_data->bucket_unit_of_measure =
1291
0
      resp->metadata.bucket_unit_of_measure;
1292
0
  meta_data->reserved1 = 0;
1293
0
  meta_data->bucket_data_type = resp->metadata.bucket_data_type;
1294
0
  meta_data->reserved2 = 0;
1295
0
  *bucket_offsets_size =
1296
0
      *data_size - sizeof(struct nsm_histogram_format_metadata);
1297
1298
0
  dataCopy(resp->bucket_offsets, bucket_offsets,
1299
0
     meta_data->num_of_buckets, meta_data->bucket_data_type);
1300
0
  letohArrayData(bucket_offsets, meta_data->num_of_buckets,
1301
0
           meta_data->bucket_data_type);
1302
1303
0
  return NSM_SW_SUCCESS;
1304
0
}
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
0
{
1337
0
  if (msg == NULL || histogram_id == NULL || parameter == NULL) {
1338
0
    return NSM_SW_ERROR_NULL;
1339
0
  }
1340
1341
0
  if (msg_len <
1342
0
      sizeof(struct nsm_msg_hdr) + sizeof(nsm_get_histogram_data_req)) {
1343
0
    return NSM_SW_ERROR_LENGTH;
1344
0
  }
1345
1346
0
  nsm_get_histogram_data_req *request =
1347
0
      (nsm_get_histogram_data_req *)msg->payload;
1348
1349
0
  if (request->hdr.data_size <
1350
0
      sizeof(request->histogram_id) + sizeof(request->parameter)) {
1351
0
    return NSM_SW_ERROR_DATA;
1352
0
  }
1353
1354
0
  *histogram_id = le32toh(request->histogram_id);
1355
0
  *parameter = le16toh(request->parameter);
1356
1357
0
  return NSM_SW_SUCCESS;
1358
0
}
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
0
{
1413
0
  if (data_size == NULL || bucket_data_type == NULL ||
1414
0
      num_of_buckets == NULL || bucket_data == NULL ||
1415
0
      bucket_data_size == NULL) {
1416
0
    return NSM_SW_ERROR_NULL;
1417
0
  }
1418
1419
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1420
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1421
0
    return rc;
1422
0
  }
1423
1424
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1425
0
        sizeof(struct nsm_get_histogram_data_resp)) {
1426
0
    return NSM_SW_ERROR_LENGTH;
1427
0
  }
1428
1429
0
  struct nsm_get_histogram_data_resp *resp =
1430
0
      (struct nsm_get_histogram_data_resp *)msg->payload;
1431
1432
0
  *data_size = le16toh(resp->hdr.data_size);
1433
0
  *bucket_data_type = resp->bucket_data_type;
1434
0
  *num_of_buckets = le16toh(resp->num_of_buckets);
1435
0
  *bucket_data_size = *data_size - sizeof(resp->num_of_buckets) -
1436
0
          sizeof(resp->bucket_data_type);
1437
1438
0
  dataCopy(resp->bucket_data, bucket_data, *num_of_buckets,
1439
0
     *bucket_data_type);
1440
0
  letohArrayData(bucket_data, *num_of_buckets, *bucket_data_type);
1441
1442
0
  return NSM_SW_SUCCESS;
1443
0
}