Coverage Report

Created: 2026-07-16 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nsmd/libnsm/firmware-utils.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 "firmware-utils.h"
19
20
#include <endian.h>
21
#include <stdio.h>
22
#include <string.h>
23
24
#define DBG1(x)
25
#define DBG2(x)
26
#define DBGW(x)
27
0
#define DBGE(x) x
28
29
struct nsm_firmware_aggregate_tag {
30
  uint8_t tag;
31
  uint8_t valid : 1;
32
  uint8_t length : 3;
33
  uint8_t reserved : 4;
34
  uint8_t data[1];
35
} __attribute__((packed));
36
37
void printArrayAsHex(const uint8_t *array, size_t size)
38
0
{
39
0
  for (size_t i = 0; i < size; ++i) {
40
0
    printf("%02X ", array[i]);
41
0
  }
42
0
  printf("\n");
43
0
}
44
45
void encode_nsm_firmware_aggregate_tag_uint8(uint8_t **buffer, uint8_t tag,
46
               uint8_t value,
47
               uint16_t *buffer_size)
48
0
{
49
0
  struct nsm_firmware_aggregate_tag *field =
50
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
51
0
  field->tag = tag;
52
0
  field->valid = 1;
53
0
  field->length = 0;
54
0
  field->reserved = 0;
55
0
  field->data[0] = value;
56
0
  *buffer +=
57
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1;
58
0
  *buffer_size +=
59
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1;
60
0
}
61
62
void encode_nsm_firmware_aggregate_tag_uint16(uint8_t **buffer, uint8_t tag,
63
                uint16_t value,
64
                uint16_t *buffer_size)
65
0
{
66
0
  struct nsm_firmware_aggregate_tag *field =
67
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
68
0
  field->tag = tag;
69
0
  field->valid = 1;
70
0
  field->length = 1;
71
0
  field->reserved = 0;
72
0
  value = htole16(value);
73
0
  memcpy(field->data, &value, sizeof(uint16_t));
74
0
  *buffer +=
75
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1;
76
0
  *buffer_size +=
77
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1;
78
0
}
79
80
void encode_nsm_firmware_aggregate_tag_uint32(uint8_t **buffer, uint8_t tag,
81
                uint32_t value,
82
                uint16_t *buffer_size)
83
0
{
84
0
  struct nsm_firmware_aggregate_tag *field =
85
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
86
0
  field->tag = tag;
87
0
  field->valid = 1;
88
0
  field->length = 2;
89
0
  field->reserved = 0;
90
0
  value = htole32(value);
91
0
  memcpy(field->data, &value, sizeof(uint32_t));
92
0
  *buffer +=
93
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1;
94
0
  *buffer_size +=
95
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1;
96
0
}
97
98
void encode_nsm_firmware_aggregate_tag_uint64(uint8_t **buffer, uint8_t tag,
99
                uint64_t value,
100
                uint16_t *buffer_size)
101
0
{
102
0
  struct nsm_firmware_aggregate_tag *field =
103
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
104
0
  field->tag = tag;
105
0
  field->valid = 1;
106
0
  field->length = 3;
107
0
  field->reserved = 0;
108
0
  value = htole64(value);
109
0
  memcpy(field->data, &value, sizeof(uint64_t));
110
0
  *buffer +=
111
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1;
112
0
  *buffer_size +=
113
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1;
114
0
}
115
116
void encode_nsm_firmware_aggregate_tag_uint8_array(uint8_t **buffer,
117
               uint8_t tag, uint8_t *value,
118
               uint16_t *buffer_size)
119
0
{
120
0
  struct nsm_firmware_aggregate_tag *field =
121
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
122
0
  field->tag = tag;
123
0
  field->valid = 1;
124
0
  field->length = 4;
125
0
  field->reserved = 0;
126
0
  memcpy(field->data, value, 16);
127
0
  *buffer += sizeof(struct nsm_firmware_aggregate_tag) + 16 - 1;
128
0
  *buffer_size += sizeof(struct nsm_firmware_aggregate_tag) + 16 - 1;
129
0
}
130
131
bool decode_nsm_firmware_aggregate_tag_uint8(uint8_t **buffer, uint8_t *tag,
132
               uint8_t *valid, uint8_t *value,
133
               uint16_t *buffer_size)
134
0
{
135
0
  if (*buffer_size <
136
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1) {
137
0
    return false;
138
0
  }
139
0
  struct nsm_firmware_aggregate_tag *field =
140
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
141
0
  *tag = field->tag;
142
0
  *valid = field->valid;
143
0
  if (field->valid) {
144
0
    *value = field->data[0];
145
0
  }
146
0
  *buffer +=
147
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1;
148
0
  *buffer_size -=
149
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint8_t) - 1;
150
0
  return true;
151
0
}
152
153
bool decode_nsm_firmware_aggregate_tag_uint16(uint8_t **buffer, uint8_t *tag,
154
                uint8_t *valid, uint16_t *value,
155
                uint16_t *buffer_size)
156
0
{
157
0
  if (*buffer_size <
158
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1) {
159
0
    return false;
160
0
  }
161
0
  struct nsm_firmware_aggregate_tag *field =
162
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
163
0
  *tag = field->tag;
164
0
  *valid = field->valid;
165
0
  if (field->valid) {
166
0
    memcpy(value, field->data, sizeof(uint16_t));
167
0
    *value = le16toh(*value);
168
0
  }
169
0
  *buffer +=
170
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1;
171
0
  *buffer_size -=
172
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint16_t) - 1;
173
0
  return true;
174
0
}
175
176
bool decode_nsm_firmware_aggregate_tag_uint32(uint8_t **buffer, uint8_t *tag,
177
                uint8_t *valid, uint32_t *value,
178
                uint16_t *buffer_size)
179
0
{
180
0
  if (*buffer_size <
181
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1) {
182
0
    return false;
183
0
  }
184
0
  struct nsm_firmware_aggregate_tag *field =
185
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
186
0
  *tag = field->tag;
187
0
  *valid = field->valid;
188
0
  if (field->valid) {
189
0
    memcpy(value, field->data, sizeof(uint32_t));
190
0
    *value = le32toh(*value);
191
0
  }
192
0
  *buffer +=
193
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1;
194
0
  *buffer_size -=
195
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint32_t) - 1;
196
0
  return true;
197
0
}
198
199
bool decode_nsm_firmware_aggregate_tag_uint64(uint8_t **buffer, uint8_t *tag,
200
                uint8_t *valid, uint64_t *value,
201
                uint16_t *buffer_size)
202
0
{
203
0
  if (*buffer_size <
204
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1) {
205
0
    return false;
206
0
  }
207
0
  struct nsm_firmware_aggregate_tag *field =
208
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
209
0
  *tag = field->tag;
210
0
  *valid = field->valid;
211
0
  if (field->valid) {
212
0
    memcpy(value, field->data, sizeof(uint64_t));
213
0
    *value = le64toh(*value);
214
0
  }
215
0
  *buffer +=
216
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1;
217
0
  *buffer_size -=
218
0
      sizeof(struct nsm_firmware_aggregate_tag) + sizeof(uint64_t) - 1;
219
0
  return true;
220
0
}
221
222
bool decode_nsm_firmware_aggregate_tag_uint8_array(uint8_t **buffer,
223
               uint8_t *tag, uint8_t *valid,
224
               uint8_t *value,
225
               uint16_t *buffer_size)
226
0
{
227
0
  uint16_t length;
228
0
  if (*buffer_size < sizeof(struct nsm_firmware_aggregate_tag) + 4 - 1) {
229
0
    return false;
230
0
  }
231
232
0
  struct nsm_firmware_aggregate_tag *field =
233
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
234
0
  *tag = field->tag;
235
0
  *valid = field->valid;
236
0
  length = 1 << field->length;
237
0
  if (*buffer_size <
238
0
      sizeof(struct nsm_firmware_aggregate_tag) + length - 1) {
239
0
    return false;
240
0
  }
241
242
0
  if (field->valid) {
243
0
    memcpy(value, field->data, length);
244
0
  }
245
246
0
  *buffer += sizeof(struct nsm_firmware_aggregate_tag) + length - 1;
247
0
  *buffer_size -= sizeof(struct nsm_firmware_aggregate_tag) + length - 1;
248
0
  return true;
249
0
}
250
251
/**
252
 * Skip the tag data by advancing the pointer
253
 * @param buffer: pointer to the buffer
254
 * @param buffer_size: size of the buffer
255
 * @return true if the tag is skipped, false otherwise
256
 */
257
bool decode_nsm_firmware_aggregate_tag_skip(uint8_t **buffer,
258
              uint16_t *buffer_size)
259
0
{
260
0
  if (*buffer_size < sizeof(struct nsm_firmware_aggregate_tag)) {
261
0
    return false;
262
0
  }
263
264
0
  struct nsm_firmware_aggregate_tag *field =
265
0
      (struct nsm_firmware_aggregate_tag *)*buffer;
266
267
0
  size_t data_len = 1 << field->length;
268
0
  size_t consumed_len =
269
0
      sizeof(struct nsm_firmware_aggregate_tag) + data_len - 1;
270
271
0
  if (*buffer_size < consumed_len) {
272
0
    return false;
273
0
  }
274
275
0
  *buffer += consumed_len;
276
0
  *buffer_size -= consumed_len;
277
0
  return true;
278
0
}
279
280
int decode_nsm_query_get_erot_state_parameters_req(
281
    const struct nsm_msg *msg, size_t msg_len,
282
    struct nsm_firmware_erot_state_info_req *fw_req)
283
0
{
284
0
  if (msg == NULL || fw_req == NULL) {
285
0
    return NSM_SW_ERROR_NULL;
286
0
  }
287
288
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
289
0
        sizeof(struct nsm_firmware_get_erot_state_info_req)) {
290
0
    return NSM_SW_ERROR_LENGTH;
291
0
  }
292
293
0
  struct nsm_firmware_get_erot_state_info_req *request =
294
0
      (struct nsm_firmware_get_erot_state_info_req *)msg->payload;
295
0
  if (request->hdr.data_size < sizeof(*fw_req)) {
296
0
    return NSM_SW_ERROR_DATA;
297
0
  }
298
299
0
  *fw_req = request->fq_req;
300
301
0
  return NSM_SW_SUCCESS;
302
0
}
303
304
int encode_nsm_query_get_erot_state_parameters_req(
305
    uint8_t instance_id, const struct nsm_firmware_erot_state_info_req *fw_req,
306
    struct nsm_msg *msg)
307
0
{
308
0
  if (msg == NULL) {
309
0
    return NSM_SW_ERROR_NULL;
310
0
  }
311
312
0
  struct nsm_header_info header = {0};
313
0
  header.nsm_msg_type = NSM_REQUEST;
314
0
  header.instance_id = instance_id;
315
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
316
317
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
318
0
  if (rc != NSM_SUCCESS) {
319
0
    return rc;
320
0
  }
321
322
0
  struct nsm_firmware_get_erot_state_info_req *request =
323
0
      (struct nsm_firmware_get_erot_state_info_req *)msg->payload;
324
0
  request->hdr.command = NSM_FW_GET_EROT_STATE_INFORMATION;
325
0
  request->hdr.data_size =
326
0
      htole16(sizeof(struct nsm_firmware_erot_state_info_req));
327
0
  memcpy(&request->fq_req, fw_req,
328
0
         sizeof(struct nsm_firmware_erot_state_info_req));
329
330
0
  return NSM_SW_SUCCESS;
331
0
}
332
333
int encode_nsm_query_get_erot_state_parameters_resp(
334
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
335
    struct nsm_firmware_erot_state_info_resp *fw_info, struct nsm_msg *msg)
336
0
{
337
0
  if (msg == NULL) {
338
0
    return NSM_SW_ERROR_NULL;
339
0
  }
340
341
0
  struct nsm_header_info header = {0};
342
0
  header.nsm_msg_type = NSM_RESPONSE;
343
0
  header.instance_id = instance_id;
344
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
345
346
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
347
0
  if (rc != NSM_SW_SUCCESS) {
348
0
    return rc;
349
0
  }
350
351
0
  if (cc != NSM_SUCCESS) {
352
0
    return encode_reason_code(
353
0
        cc, reason_code, NSM_FW_GET_EROT_STATE_INFORMATION, msg);
354
0
  }
355
356
0
  struct nsm_firmware_get_erot_state_info_resp *response =
357
0
      (struct nsm_firmware_get_erot_state_info_resp *)msg->payload;
358
0
  response->hdr.command = NSM_FW_GET_EROT_STATE_INFORMATION;
359
0
  response->hdr.completion_code = cc;
360
361
0
  uint16_t telemetry_count = 0;
362
0
  uint16_t msg_size = sizeof(struct nsm_common_telemetry_resp);
363
364
0
  uint8_t *ptr = &(response->payload[0]);
365
366
0
  encode_nsm_firmware_aggregate_tag_uint8(
367
0
      &ptr, NSM_FIRMWARE_BACKGROUND_COPY_POLICY,
368
0
      fw_info->fq_resp_hdr.background_copy_policy, &msg_size);
369
0
  telemetry_count++;
370
0
  encode_nsm_firmware_aggregate_tag_uint8(
371
0
      &ptr, NSM_FIRMWARE_ACTIVE_FIRMWARE_SLOT,
372
0
      fw_info->fq_resp_hdr.active_slot, &msg_size);
373
0
  telemetry_count++;
374
0
  encode_nsm_firmware_aggregate_tag_uint8(
375
0
      &ptr, NSM_FIRMWARE_ACTIVE_KEY_SET,
376
0
      fw_info->fq_resp_hdr.active_keyset, &msg_size);
377
0
  telemetry_count++;
378
0
  encode_nsm_firmware_aggregate_tag_uint16(
379
0
      &ptr, NSM_FIRMWARE_MINIMUM_SECURITY_VERSION_NUMBER,
380
0
      fw_info->fq_resp_hdr.minimum_security_version, &msg_size);
381
0
  telemetry_count++;
382
0
  encode_nsm_firmware_aggregate_tag_uint8(
383
0
      &ptr, NSM_FIRMWARE_INBAND_UPDATE_POLICY,
384
0
      fw_info->fq_resp_hdr.inband_update_policy, &msg_size);
385
0
  telemetry_count++;
386
0
  encode_nsm_firmware_aggregate_tag_uint64(
387
0
      &ptr, NSM_FIRMWARE_BOOT_STATUS_CODE,
388
0
      fw_info->fq_resp_hdr.boot_status_code, &msg_size);
389
0
  telemetry_count++;
390
0
  encode_nsm_firmware_aggregate_tag_uint8(
391
0
      &ptr, NSM_FIRMWARE_FIRMWARE_SLOT_COUNT,
392
0
      fw_info->fq_resp_hdr.firmware_slot_count, &msg_size);
393
0
  telemetry_count++;
394
395
0
  for (int i = 0; i < fw_info->fq_resp_hdr.firmware_slot_count; i++) {
396
0
    encode_nsm_firmware_aggregate_tag_uint8(
397
0
        &ptr, NSM_FIRMWARE_FIRMWARE_SLOT_ID,
398
0
        fw_info->slot_info[i].slot_id, &msg_size);
399
0
    telemetry_count++;
400
0
    encode_nsm_firmware_aggregate_tag_uint8_array(
401
0
        &ptr, NSM_FIRMWARE_FIRMWARE_VERSION_STRING,
402
0
        (uint8_t *)(&(
403
0
      fw_info->slot_info[i].firmware_version_string[0])),
404
0
        &msg_size);
405
0
    telemetry_count++;
406
0
    encode_nsm_firmware_aggregate_tag_uint32(
407
0
        &ptr, NSM_FIRMWARE_VERSION_COMPARISON_STAMP,
408
0
        fw_info->slot_info[i].version_comparison_stamp, &msg_size);
409
0
    telemetry_count++;
410
0
    encode_nsm_firmware_aggregate_tag_uint8(
411
0
        &ptr, NSM_FIRMWARE_BUILD_TYPE,
412
0
        fw_info->slot_info[i].build_type, &msg_size);
413
0
    telemetry_count++;
414
0
    encode_nsm_firmware_aggregate_tag_uint8(
415
0
        &ptr, NSM_FIRMWARE_SIGNING_TYPE,
416
0
        fw_info->slot_info[i].signing_type, &msg_size);
417
0
    telemetry_count++;
418
0
    encode_nsm_firmware_aggregate_tag_uint8(
419
0
        &ptr, NSM_FIRMWARE_WRITE_PROTECT_STATE,
420
0
        fw_info->slot_info[i].write_protect_state, &msg_size);
421
0
    telemetry_count++;
422
0
    encode_nsm_firmware_aggregate_tag_uint8(
423
0
        &ptr, NSM_FIRMWARE_FIRMWARE_STATE,
424
0
        fw_info->slot_info[i].firmware_state, &msg_size);
425
0
    telemetry_count++;
426
0
    encode_nsm_firmware_aggregate_tag_uint16(
427
0
        &ptr, NSM_FIRMWARE_SECURITY_VERSION_NUMBER,
428
0
        fw_info->slot_info[i].security_version_number, &msg_size);
429
0
    telemetry_count++;
430
0
    encode_nsm_firmware_aggregate_tag_uint16(
431
0
        &ptr, NSM_FIRMWARE_SIGNING_KEY_INDEX,
432
0
        fw_info->slot_info[i].signing_key_index, &msg_size);
433
0
    telemetry_count++;
434
0
  }
435
436
0
  response->hdr.telemetry_count = htole16(telemetry_count);
437
438
0
  DBG1(printf("Telemetry count = %u, resp buffer (size = %u):\n",
439
0
        (uint32_t)telemetry_count, (uint32_t)msg_size);)
440
0
  DBG1(printArrayAsHex(&(response->payload[0]), msg_size);)
441
442
0
  return NSM_SW_SUCCESS;
443
0
}
444
445
int decode_nsm_query_firmware_header_information(
446
    struct nsm_firmware_erot_state_info_hdr_resp *fw_info_hdr, uint8_t **ptr,
447
    uint16_t *payload_size, uint16_t *telemetry_count)
448
0
{
449
0
  uint8_t tag, valid;
450
0
  bool rc_ok;
451
452
0
  while ((*payload_size >= sizeof(struct nsm_firmware_aggregate_tag)) &&
453
0
         (*telemetry_count > 0)) {
454
0
    struct nsm_firmware_aggregate_tag *field =
455
0
        (struct nsm_firmware_aggregate_tag *)*ptr;
456
0
    tag = field->tag;
457
458
0
    if (tag == NSM_FIRMWARE_BACKGROUND_COPY_POLICY) {
459
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
460
0
          ptr, &tag, &valid,
461
0
          &(fw_info_hdr->background_copy_policy),
462
0
          payload_size);
463
0
      if (rc_ok) {
464
0
        (*telemetry_count)--;
465
0
        DBG2(printf(
466
0
           "Decoded "
467
0
           "NSM_FIRMWARE_BACKGROUND_COPY_POLICY, "
468
0
           "value = 0x%02x\n",
469
0
           fw_info_hdr->background_copy_policy);)
470
0
      }
471
0
    } else if (tag == NSM_FIRMWARE_ACTIVE_FIRMWARE_SLOT) {
472
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
473
0
          ptr, &tag, &valid, &(fw_info_hdr->active_slot),
474
0
          payload_size);
475
0
      if (rc_ok) {
476
0
        (*telemetry_count)--;
477
0
        DBG2(printf("Decoded "
478
0
              "NSM_FIRMWARE_ACTIVE_FIRMWARE_SLOT,"
479
0
              " value = 0x%02x\n",
480
0
              fw_info_hdr->active_slot);)
481
0
      }
482
0
    } else if (tag == NSM_FIRMWARE_ACTIVE_KEY_SET) {
483
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
484
0
          ptr, &tag, &valid, &(fw_info_hdr->active_keyset),
485
0
          payload_size);
486
0
      if (rc_ok) {
487
0
        (*telemetry_count)--;
488
0
        DBG2(printf(
489
0
           "Decoded NSM_FIRMWARE_ACTIVE_KEY_SET, "
490
0
           "value = 0x%02x\n",
491
0
           fw_info_hdr->active_keyset);)
492
0
      }
493
0
    } else if (tag ==
494
0
         NSM_FIRMWARE_MINIMUM_SECURITY_VERSION_NUMBER) {
495
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint16(
496
0
          ptr, &tag, &valid,
497
0
          &(fw_info_hdr->minimum_security_version),
498
0
          payload_size);
499
0
      if (rc_ok) {
500
0
        (*telemetry_count)--;
501
0
        DBG2(
502
0
            printf(
503
0
          "Decoded "
504
0
          "NSM_FIRMWARE_MINIMUM_SECURITY_VERSION_"
505
0
          "NUMBER, value = 0x%04x\n",
506
0
          fw_info_hdr->minimum_security_version);)
507
0
      }
508
0
    } else if (tag == NSM_FIRMWARE_INBAND_UPDATE_POLICY) {
509
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
510
0
          ptr, &tag, &valid,
511
0
          &(fw_info_hdr->inband_update_policy), payload_size);
512
0
      if (rc_ok) {
513
0
        (*telemetry_count)--;
514
0
        DBG2(printf("Decoded "
515
0
              "NSM_FIRMWARE_INBAND_UPDATE_POLICY,"
516
0
              " value = 0x%02x\n",
517
0
              fw_info_hdr->inband_update_policy);)
518
0
      }
519
0
    } else if (tag == NSM_FIRMWARE_BOOT_STATUS_CODE) {
520
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint64(
521
0
          ptr, &tag, &valid, &(fw_info_hdr->boot_status_code),
522
0
          payload_size);
523
0
      if (rc_ok) {
524
0
        (*telemetry_count)--;
525
0
        DBG2(printf("Decoded "
526
0
              "NSM_FIRMWARE_BOOT_STATUS_CODE,"
527
0
              " value = 0x%016lx\n",
528
0
              fw_info_hdr->boot_status_code);)
529
0
      }
530
0
    } else if (tag == NSM_FIRMWARE_FIRMWARE_SLOT_COUNT) {
531
0
      if (decode_nsm_firmware_aggregate_tag_uint8(
532
0
        ptr, &tag, &valid,
533
0
        &(fw_info_hdr->firmware_slot_count),
534
0
        payload_size)) {
535
0
        (*telemetry_count)--;
536
0
        DBG2(printf("Decoded "
537
0
              "NSM_FIRMWARE_FIRMWARE_SLOT_COUNT, "
538
0
              "value = 0x%02x\n",
539
0
              fw_info_hdr->firmware_slot_count);)
540
0
        break;
541
0
      }
542
0
      rc_ok = false;
543
0
    } else {
544
      /* Skip unsupported tag */
545
0
      DBG2(printf(
546
0
         "Skipping unsupported tag in header: 0x%02x\n",
547
0
         field->tag);)
548
0
      DBG2(printf("Left telemetries: %u, left payload: %u\n",
549
0
            (uint32_t)(*telemetry_count),
550
0
            (uint32_t)(*payload_size));)
551
0
      (*telemetry_count)--;
552
0
      rc_ok = decode_nsm_firmware_aggregate_tag_skip(
553
0
          ptr, payload_size);
554
0
      if (!rc_ok) {
555
0
        DBGE(printf("Error: The decoded message header "
556
0
              "is not "
557
0
              "properly encoded\n");)
558
0
        DBGE(printf("Left telemetries: %u, left "
559
0
              "payload: %u\n",
560
0
              (uint32_t)(*telemetry_count),
561
0
              (uint32_t)(*payload_size));)
562
0
        return NSM_SW_ERROR_LENGTH;
563
0
      }
564
0
    }
565
566
0
    if (!rc_ok) {
567
0
      DBGE(printf("Error: The decoded message header is not "
568
0
            "properly encoded\n");)
569
0
      DBGE(printf("Left telemetries: %u, left payload: %u\n",
570
0
            (uint32_t)(*telemetry_count),
571
0
            (uint32_t)(*payload_size));)
572
0
      return NSM_SW_ERROR_LENGTH;
573
0
    }
574
0
  }
575
576
0
  DBG2(printf("Success in decoding the response header\n");)
577
0
  return NSM_SW_SUCCESS;
578
0
}
579
580
int decode_nsm_query_firmware_slot_information(
581
    struct nsm_firmware_slot_info *fw_slot_info, uint8_t **ptr,
582
    uint16_t *payload_size, uint16_t *telemetry_count)
583
0
{
584
0
  uint8_t tag, valid;
585
0
  bool rc_ok;
586
587
0
  if ((*payload_size < sizeof(struct nsm_firmware_aggregate_tag)) ||
588
0
      (*telemetry_count == 0)) {
589
0
    DBG2(printf("Error: Expected NSM_FIRMWARE_FIRMWARE_SLOT_ID, "
590
0
          "but there is no more tags in the message\n");)
591
0
    return NSM_SW_ERROR_DATA;
592
0
  }
593
594
0
  struct nsm_firmware_aggregate_tag *field =
595
0
      (struct nsm_firmware_aggregate_tag *)*ptr;
596
0
  tag = field->tag;
597
598
  // Firmware slot ID tag must be always as the first one
599
0
  if (tag == NSM_FIRMWARE_FIRMWARE_SLOT_ID) {
600
0
    if (!decode_nsm_firmware_aggregate_tag_uint8(
601
0
      ptr, &tag, &valid, &(fw_slot_info->slot_id),
602
0
      payload_size)) {
603
0
      return NSM_SW_ERROR_LENGTH;
604
0
    }
605
0
    (*telemetry_count)--;
606
0
    DBG2(printf(
607
0
       "Decoded NSM_FIRMWARE_FIRMWARE_SLOT_ID, value = %u\n",
608
0
       fw_slot_info->slot_id);)
609
0
  } else {
610
0
    return NSM_SW_ERROR_DATA;
611
0
  }
612
613
0
  while ((*payload_size >= sizeof(struct nsm_firmware_aggregate_tag)) &&
614
0
         (*telemetry_count > 0)) {
615
0
    field = (struct nsm_firmware_aggregate_tag *)*ptr;
616
0
    tag = field->tag;
617
618
0
    if (tag == NSM_FIRMWARE_FIRMWARE_VERSION_STRING) {
619
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint8_array(
620
0
          ptr, &tag, &valid,
621
0
          (uint8_t *)(&(
622
0
        fw_slot_info->firmware_version_string[0])),
623
0
          payload_size);
624
0
      if (rc_ok) {
625
0
        (*telemetry_count)--;
626
0
        DBG2(
627
0
            printf(
628
0
          "Decoded "
629
0
          "NSM_FIRMWARE_FIRMWARE_VERSION_STRING, "
630
0
          "value = %s\n",
631
0
          (char
632
0
               *)(fw_slot_info
633
0
                ->firmware_version_string));)
634
0
      }
635
0
    } else if (tag == NSM_FIRMWARE_VERSION_COMPARISON_STAMP) {
636
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint32(
637
0
          ptr, &tag, &valid,
638
0
          &(fw_slot_info->version_comparison_stamp),
639
0
          payload_size);
640
0
      if (rc_ok) {
641
0
        (*telemetry_count)--;
642
0
        DBG2(printf("Decoded "
643
0
              "NSM_FIRMWARE_VERSION_COMPARISON_"
644
0
              "STAMP, value = %u\n",
645
0
              fw_slot_info
646
0
            ->version_comparison_stamp);)
647
0
      }
648
0
    } else if (tag == NSM_FIRMWARE_BUILD_TYPE) {
649
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
650
0
          ptr, &tag, &valid, &(fw_slot_info->build_type),
651
0
          payload_size);
652
0
      if (rc_ok) {
653
0
        (*telemetry_count)--;
654
0
        DBG2(printf("Decoded NSM_FIRMWARE_BUILD_TYPE, "
655
0
              "value = %u\n",
656
0
              fw_slot_info->build_type);)
657
0
      }
658
0
    } else if (tag == NSM_FIRMWARE_SIGNING_TYPE) {
659
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
660
0
          ptr, &tag, &valid, &(fw_slot_info->signing_type),
661
0
          payload_size);
662
0
      if (rc_ok) {
663
0
        (*telemetry_count)--;
664
0
        DBG2(
665
0
            printf("Decoded NSM_FIRMWARE_SIGNING_TYPE, "
666
0
             "value = %u\n",
667
0
             fw_slot_info->signing_type);)
668
0
      }
669
0
    } else if (tag == NSM_FIRMWARE_WRITE_PROTECT_STATE) {
670
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
671
0
          ptr, &tag, &valid,
672
0
          &(fw_slot_info->write_protect_state), payload_size);
673
0
      if (rc_ok) {
674
0
        (*telemetry_count)--;
675
0
        DBG2(printf("Decoded "
676
0
              "NSM_FIRMWARE_WRITE_PROTECT_STATE, "
677
0
              "value = %u\n",
678
0
              fw_slot_info->write_protect_state);)
679
0
      }
680
0
    } else if (tag == NSM_FIRMWARE_FIRMWARE_STATE) {
681
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint8(
682
0
          ptr, &tag, &valid, &(fw_slot_info->firmware_state),
683
0
          payload_size);
684
0
      if (rc_ok) {
685
0
        (*telemetry_count)--;
686
0
        DBG2(printf(
687
0
           "Decoded NSM_FIRMWARE_FIRMWARE_STATE, "
688
0
           "value = %u\n",
689
0
           fw_slot_info->firmware_state);)
690
0
      }
691
0
    } else if (tag == NSM_FIRMWARE_SECURITY_VERSION_NUMBER) {
692
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint16(
693
0
          ptr, &tag, &valid,
694
0
          &(fw_slot_info->security_version_number),
695
0
          payload_size);
696
0
      if (rc_ok) {
697
0
        (*telemetry_count)--;
698
0
        DBG2(
699
0
            printf(
700
0
          "Decoded "
701
0
          "NSM_FIRMWARE_SECURITY_VERSION_NUMBER, "
702
0
          "value = %u\n",
703
0
          fw_slot_info->security_version_number);)
704
0
      }
705
0
    } else if (tag == NSM_FIRMWARE_SIGNING_KEY_INDEX) {
706
0
      rc_ok = decode_nsm_firmware_aggregate_tag_uint16(
707
0
          ptr, &tag, &valid,
708
0
          &(fw_slot_info->signing_key_index), payload_size);
709
0
      if (rc_ok) {
710
0
        (*telemetry_count)--;
711
0
        DBG2(printf("Decoded "
712
0
              "NSM_FIRMWARE_SIGNING_KEY_INDEX, "
713
0
              "value = %u\n",
714
0
              fw_slot_info->signing_key_index);)
715
0
      }
716
0
    } else if (tag == NSM_FIRMWARE_FIRMWARE_SLOT_ID) {
717
      /* we are good, we reached new firmware slot id */
718
0
      return NSM_SW_SUCCESS;
719
0
    } else {
720
      /* Skip unsupported tag */
721
0
      DBG2(printf("Skipping unsupported tag in slot "
722
0
            "information: 0x%02x\n",
723
0
            field->tag);)
724
0
      DBG2(printf("Left telemetries: %u, left payload: %u\n",
725
0
            (uint32_t)(*telemetry_count),
726
0
            (uint32_t)(*payload_size));)
727
0
      (*telemetry_count)--;
728
0
      rc_ok = decode_nsm_firmware_aggregate_tag_skip(
729
0
          ptr, payload_size);
730
0
      if (!rc_ok) {
731
0
        DBGE(printf("Error: The decoded message slot "
732
0
              "information is not properly "
733
0
              "encoded\n");)
734
0
        DBGE(printf("Left telemetries: %u, left "
735
0
              "payload: %u\n",
736
0
              (uint32_t)(*telemetry_count),
737
0
              (uint32_t)(*payload_size));)
738
0
        return NSM_SW_ERROR_LENGTH;
739
0
      }
740
0
    }
741
742
0
    if (!rc_ok) {
743
0
      DBGE(printf("Error: The decoded message slot "
744
0
            "information is not properly encoded\n");)
745
0
      DBGE(printf("Left telemetries: %u, left payload: %u\n",
746
0
            (uint32_t)(*telemetry_count),
747
0
            (uint32_t)(*payload_size));)
748
0
      return NSM_SW_ERROR_LENGTH;
749
0
    }
750
0
  }
751
752
0
  DBG2(printf("Success in decoding the response slot information\n");)
753
0
  return NSM_SW_SUCCESS;
754
0
}
755
756
int decode_nsm_query_get_erot_state_parameters_resp(
757
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
758
    uint16_t *reason_code, struct nsm_firmware_erot_state_info_resp *fw_resp)
759
0
{
760
0
  if (msg == NULL || fw_resp == NULL) {
761
0
    return NSM_SW_ERROR_NULL;
762
0
  }
763
764
0
  DBG1(printf("Received Resp buffer (size = %zi):\n", msg_len);)
765
0
  DBG1(printArrayAsHex(&(msg->payload[0]), msg_len);)
766
767
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
768
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
769
0
    return rc;
770
0
  }
771
772
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
773
0
        sizeof(struct nsm_firmware_aggregate_tag)) {
774
0
    return NSM_SW_ERROR_LENGTH;
775
0
  }
776
777
0
  struct nsm_firmware_get_erot_state_info_resp *resp =
778
0
      (struct nsm_firmware_get_erot_state_info_resp *)msg->payload;
779
780
0
  uint8_t *ptr = &(resp->payload[0]);
781
0
  uint16_t telemetry_count = resp->hdr.telemetry_count;
782
0
  uint16_t payload_size = (uint16_t)msg_len - sizeof(struct nsm_msg_hdr) -
783
0
        sizeof(struct nsm_common_telemetry_resp);
784
0
  DBG2(printf("Telemetry count = %u, msg max size = %u:\n",
785
0
        (uint32_t)telemetry_count, (uint32_t)payload_size);)
786
787
0
  int ret = decode_nsm_query_firmware_header_information(
788
0
      &(fw_resp->fq_resp_hdr), &ptr, &payload_size, &telemetry_count);
789
0
  if (ret) {
790
0
    DBGE(printf("Full payload (len = %zi):\n", msg_len);)
791
0
    DBGE(printArrayAsHex((const uint8_t *)msg, msg_len);)
792
0
    return ret;
793
0
  }
794
795
0
  DBG2(printf("Payload remaining size = %u):\n", (uint32_t)payload_size);)
796
0
  if (fw_resp->fq_resp_hdr.firmware_slot_count > 0) {
797
0
    int slot_info_len = sizeof(struct nsm_firmware_slot_info) *
798
0
            fw_resp->fq_resp_hdr.firmware_slot_count;
799
0
    fw_resp->slot_info = malloc(slot_info_len);
800
0
    memset((char *)(fw_resp->slot_info), 0, slot_info_len);
801
802
0
    for (int i = 0; i < fw_resp->fq_resp_hdr.firmware_slot_count;
803
0
         i++) {
804
0
      int ret = decode_nsm_query_firmware_slot_information(
805
0
          &(fw_resp->slot_info[i]), &ptr, &payload_size,
806
0
          &telemetry_count);
807
0
      if (ret) {
808
0
        DBGE(printf("Full payload (len = %zi):\n",
809
0
              msg_len);)
810
0
        DBGE(printArrayAsHex((const uint8_t *)msg,
811
0
                 msg_len);)
812
0
        return ret;
813
0
      }
814
0
    }
815
0
  } else {
816
0
    fw_resp->slot_info = NULL;
817
0
  }
818
819
0
  return NSM_SW_SUCCESS;
820
0
}
821
822
int encode_nsm_firmware_irreversible_config_req(
823
    uint8_t instance_id,
824
    const struct nsm_firmware_irreversible_config_req *fw_req,
825
    struct nsm_msg *msg)
826
0
{
827
0
  if (msg == NULL) {
828
0
    return NSM_SW_ERROR_NULL;
829
0
  }
830
0
  struct nsm_header_info header = {0};
831
0
  header.nsm_msg_type = NSM_REQUEST;
832
0
  header.instance_id = instance_id;
833
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
834
835
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
836
0
  if (rc != NSM_SUCCESS) {
837
0
    return rc;
838
0
  }
839
840
0
  struct nsm_firmware_irreversible_config_req_command *request =
841
0
      (struct nsm_firmware_irreversible_config_req_command *)msg->payload;
842
0
  request->hdr.command = NSM_FW_IRREVERSABLE_CONFIGURATION;
843
0
  request->hdr.data_size =
844
0
      sizeof(struct nsm_firmware_irreversible_config_req);
845
0
  memcpy(&request->irreversible_cfg_req, fw_req,
846
0
         sizeof(struct nsm_firmware_irreversible_config_req));
847
848
0
  return NSM_SW_SUCCESS;
849
0
}
850
851
int decode_nsm_firmware_irreversible_config_req(
852
    const struct nsm_msg *msg, size_t msg_len,
853
    struct nsm_firmware_irreversible_config_req *fw_req)
854
0
{
855
0
  if (msg == NULL || fw_req == NULL) {
856
0
    return NSM_SW_ERROR_NULL;
857
0
  }
858
859
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
860
0
        sizeof(struct nsm_firmware_irreversible_config_req)) {
861
0
    return NSM_SW_ERROR_LENGTH;
862
0
  }
863
864
0
  struct nsm_firmware_irreversible_config_req_command *request =
865
0
      (struct nsm_firmware_irreversible_config_req_command *)msg->payload;
866
0
  if (request->hdr.data_size < sizeof(*fw_req)) {
867
0
    return NSM_SW_ERROR_DATA;
868
0
  }
869
870
0
  *fw_req = request->irreversible_cfg_req;
871
872
0
  return NSM_SW_SUCCESS;
873
0
}
874
875
int encode_nsm_firmware_irreversible_config_request_0_resp(
876
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
877
    struct nsm_firmware_irreversible_config_request_0_resp *cfg_resp,
878
    struct nsm_msg *msg)
879
0
{
880
0
  if (msg == NULL) {
881
0
    return NSM_SW_ERROR_NULL;
882
0
  }
883
884
0
  struct nsm_header_info header = {0};
885
0
  header.nsm_msg_type = NSM_RESPONSE;
886
0
  header.instance_id = instance_id;
887
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
888
889
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
890
0
  if (rc != NSM_SW_SUCCESS) {
891
0
    return rc;
892
0
  }
893
894
0
  if (cc != NSM_SUCCESS) {
895
0
    return encode_reason_code(
896
0
        cc, reason_code, NSM_FW_IRREVERSABLE_CONFIGURATION, msg);
897
0
  }
898
899
0
  struct nsm_firmware_irreversible_config_request_0_resp_command
900
0
      *response =
901
0
    (struct nsm_firmware_irreversible_config_request_0_resp_command
902
0
         *)msg->payload;
903
0
  response->hdr.command = NSM_FW_IRREVERSABLE_CONFIGURATION;
904
0
  response->hdr.completion_code = cc;
905
906
0
  uint16_t msg_size =
907
0
      sizeof(struct nsm_common_resp) +
908
0
      sizeof(struct nsm_firmware_irreversible_config_request_0_resp);
909
910
0
  response->hdr.data_size = htole16(msg_size);
911
912
0
  memcpy(&(response->irreversible_cfg_query), cfg_resp,
913
0
         sizeof(struct nsm_firmware_irreversible_config_request_0_resp));
914
915
0
  return NSM_SW_SUCCESS;
916
0
}
917
918
int encode_nsm_firmware_irreversible_config_request_1_resp(uint8_t instance_id,
919
                 uint8_t cc,
920
                 uint16_t reason_code,
921
                 struct nsm_msg *msg)
922
0
{
923
0
  if (msg == NULL) {
924
0
    return NSM_SW_ERROR_NULL;
925
0
  }
926
927
0
  struct nsm_header_info header = {0};
928
0
  header.nsm_msg_type = NSM_RESPONSE;
929
0
  header.instance_id = instance_id;
930
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
931
932
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
933
0
  if (rc != NSM_SW_SUCCESS) {
934
0
    return rc;
935
0
  }
936
937
0
  if (cc != NSM_SUCCESS) {
938
0
    return encode_reason_code(
939
0
        cc, reason_code, NSM_FW_IRREVERSABLE_CONFIGURATION, msg);
940
0
  }
941
942
0
  struct nsm_firmware_irreversible_config_request_1_resp_command
943
0
      *response =
944
0
    (struct nsm_firmware_irreversible_config_request_1_resp_command
945
0
         *)msg->payload;
946
0
  response->hdr.command = NSM_FW_IRREVERSABLE_CONFIGURATION;
947
0
  response->hdr.completion_code = cc;
948
949
0
  uint16_t msg_size = sizeof(struct nsm_common_resp);
950
951
0
  response->hdr.data_size = htole16(msg_size);
952
953
0
  return NSM_SW_SUCCESS;
954
0
}
955
956
int encode_nsm_firmware_irreversible_config_request_2_resp(
957
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
958
    struct nsm_firmware_irreversible_config_request_2_resp *cfg_resp,
959
    struct nsm_msg *msg)
960
0
{
961
0
  if (msg == NULL) {
962
0
    return NSM_SW_ERROR_NULL;
963
0
  }
964
965
0
  struct nsm_header_info header = {0};
966
0
  header.nsm_msg_type = NSM_RESPONSE;
967
0
  header.instance_id = instance_id;
968
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
969
970
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
971
0
  if (rc != NSM_SW_SUCCESS) {
972
0
    return rc;
973
0
  }
974
975
0
  if (cc != NSM_SUCCESS) {
976
0
    return encode_reason_code(
977
0
        cc, reason_code, NSM_FW_IRREVERSABLE_CONFIGURATION, msg);
978
0
  }
979
980
0
  struct nsm_firmware_irreversible_config_request_2_resp_command
981
0
      *response =
982
0
    (struct nsm_firmware_irreversible_config_request_2_resp_command
983
0
         *)msg->payload;
984
0
  response->hdr.command = NSM_FW_IRREVERSABLE_CONFIGURATION;
985
0
  response->hdr.completion_code = cc;
986
987
0
  uint16_t msg_size =
988
0
      sizeof(struct nsm_common_resp) +
989
0
      sizeof(struct nsm_firmware_irreversible_config_request_2_resp);
990
991
0
  response->hdr.data_size = htole16(msg_size);
992
993
0
  memcpy(&(response->irreversible_cfg_enable_response), cfg_resp,
994
0
         sizeof(struct nsm_firmware_irreversible_config_request_2_resp));
995
996
0
  return NSM_SW_SUCCESS;
997
0
}
998
999
int decode_nsm_firmware_irreversible_config_request_0_resp(
1000
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
1001
    uint16_t *reason_code,
1002
    struct nsm_firmware_irreversible_config_request_0_resp *cfg_resp)
1003
0
{
1004
0
  if (msg == NULL || cfg_resp == NULL) {
1005
0
    return NSM_SW_ERROR_NULL;
1006
0
  }
1007
1008
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1009
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1010
0
    return rc;
1011
0
  }
1012
1013
0
  if (msg_len <
1014
0
      sizeof(struct nsm_msg_hdr) +
1015
0
    sizeof(
1016
0
        struct nsm_firmware_irreversible_config_request_0_resp)) {
1017
0
    return NSM_SW_ERROR_LENGTH;
1018
0
  }
1019
1020
0
  struct nsm_firmware_irreversible_config_request_0_resp_command *resp =
1021
0
      (struct nsm_firmware_irreversible_config_request_0_resp_command *)
1022
0
    msg->payload;
1023
1024
0
  memcpy(cfg_resp, &(resp->irreversible_cfg_query),
1025
0
         sizeof(struct nsm_firmware_irreversible_config_request_0_resp));
1026
1027
0
  return NSM_SW_SUCCESS;
1028
0
}
1029
1030
int decode_nsm_firmware_irreversible_config_request_1_resp(
1031
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
1032
    uint16_t *reason_code)
1033
0
{
1034
0
  if (msg == NULL) {
1035
0
    return NSM_SW_ERROR_NULL;
1036
0
  }
1037
1038
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1039
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1040
0
    return rc;
1041
0
  }
1042
1043
0
  if (msg_len < sizeof(struct nsm_msg_hdr)) {
1044
0
    return NSM_SW_ERROR_LENGTH;
1045
0
  }
1046
1047
0
  return NSM_SW_SUCCESS;
1048
0
}
1049
1050
int decode_nsm_firmware_irreversible_config_request_2_resp(
1051
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
1052
    uint16_t *reason_code,
1053
    struct nsm_firmware_irreversible_config_request_2_resp *cfg_resp)
1054
0
{
1055
0
  if (msg == NULL || cfg_resp == NULL) {
1056
0
    return NSM_SW_ERROR_NULL;
1057
0
  }
1058
1059
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1060
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1061
0
    return rc;
1062
0
  }
1063
1064
0
  if (msg_len <
1065
0
      sizeof(struct nsm_msg_hdr) +
1066
0
    sizeof(
1067
0
        struct nsm_firmware_irreversible_config_request_2_resp)) {
1068
0
    return NSM_SW_ERROR_LENGTH;
1069
0
  }
1070
1071
0
  struct nsm_firmware_irreversible_config_request_2_resp_command *resp =
1072
0
      (struct nsm_firmware_irreversible_config_request_2_resp_command *)
1073
0
    msg->payload;
1074
1075
0
  memcpy(cfg_resp, &(resp->irreversible_cfg_enable_response),
1076
0
         sizeof(struct nsm_firmware_irreversible_config_request_2_resp));
1077
1078
0
  return NSM_SW_SUCCESS;
1079
0
}
1080
1081
int decode_nsm_code_auth_key_perm_query_req(
1082
    const struct nsm_msg *msg, size_t msg_len,
1083
    uint16_t *component_classification, uint16_t *component_identifier,
1084
    uint8_t *component_classification_index)
1085
0
{
1086
0
  if (msg == NULL || component_classification == NULL ||
1087
0
      component_identifier == NULL ||
1088
0
      component_classification_index == NULL) {
1089
0
    return NSM_SW_ERROR_NULL;
1090
0
  }
1091
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1092
0
        sizeof(struct nsm_code_auth_key_perm_query_req)) {
1093
0
    return NSM_SW_ERROR_LENGTH;
1094
0
  }
1095
1096
0
  struct nsm_code_auth_key_perm_query_req *req =
1097
0
      (struct nsm_code_auth_key_perm_query_req *)msg->payload;
1098
0
  if (req->hdr.data_size <
1099
0
      sizeof(struct nsm_code_auth_key_perm_query_req) -
1100
0
    NSM_REQUEST_CONVENTION_LEN) {
1101
0
    return NSM_SW_ERROR_DATA;
1102
0
  }
1103
0
  *component_classification = req->component_classification;
1104
0
  *component_identifier = req->component_identifier;
1105
0
  *component_classification_index = req->component_classification_index;
1106
1107
0
  return NSM_SW_SUCCESS;
1108
0
}
1109
1110
int encode_nsm_code_auth_key_perm_query_req(
1111
    uint8_t instance_id, uint16_t component_classification,
1112
    uint16_t component_identifier, uint8_t component_classification_index,
1113
    struct nsm_msg *msg)
1114
0
{
1115
0
  if (msg == NULL) {
1116
0
    return NSM_SW_ERROR_NULL;
1117
0
  }
1118
1119
0
  struct nsm_header_info header = {0};
1120
0
  header.nsm_msg_type = NSM_REQUEST;
1121
0
  header.instance_id = instance_id;
1122
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
1123
1124
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1125
0
  if (rc != NSM_SUCCESS) {
1126
0
    return rc;
1127
0
  }
1128
1129
0
  struct nsm_code_auth_key_perm_query_req *req =
1130
0
      (struct nsm_code_auth_key_perm_query_req *)msg->payload;
1131
0
  req->hdr.command = NSM_FW_QUERY_CODE_AUTH_KEY_PERM;
1132
0
  req->hdr.data_size =
1133
0
      htole16(sizeof(struct nsm_code_auth_key_perm_query_req) -
1134
0
        NSM_REQUEST_CONVENTION_LEN);
1135
0
  req->component_classification = component_classification;
1136
0
  req->component_identifier = component_identifier;
1137
0
  req->component_classification_index = component_classification_index;
1138
1139
0
  return NSM_SUCCESS;
1140
0
}
1141
1142
int decode_nsm_code_auth_key_perm_query_resp(
1143
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
1144
    uint16_t *reason_code, uint16_t *active_component_key_index,
1145
    uint16_t *pending_component_key_index, uint8_t *permission_bitmap_length,
1146
    uint8_t *active_component_key_perm_bitmap,
1147
    uint8_t *pending_component_key_perm_bitmap, uint8_t *efuse_key_perm_bitmap,
1148
    uint8_t *pending_efuse_key_perm_bitmap)
1149
0
{
1150
0
  if (msg == NULL || active_component_key_index == NULL ||
1151
0
      pending_component_key_index == NULL ||
1152
0
      permission_bitmap_length == NULL) {
1153
0
    return NSM_SW_ERROR_NULL;
1154
0
  }
1155
1156
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1157
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1158
0
    return rc;
1159
0
  }
1160
1161
0
  size_t expected_bitmap_length =
1162
0
      msg_len - sizeof(struct nsm_msg_hdr) -
1163
0
      sizeof(struct nsm_code_auth_key_perm_query_resp);
1164
0
  struct nsm_code_auth_key_perm_query_resp *resp =
1165
0
      (struct nsm_code_auth_key_perm_query_resp *)msg->payload;
1166
0
  if (expected_bitmap_length !=
1167
0
      (size_t)resp->permission_bitmap_length * 4u) {
1168
0
    return NSM_SW_ERROR_LENGTH;
1169
0
  }
1170
0
  *active_component_key_index = resp->active_component_key_index;
1171
0
  *pending_component_key_index = resp->pending_component_key_index;
1172
0
  *permission_bitmap_length = resp->permission_bitmap_length;
1173
0
  if (active_component_key_perm_bitmap != NULL) {
1174
0
    const uint8_t *bitmap_ptr =
1175
0
        msg->payload +
1176
0
        sizeof(struct nsm_code_auth_key_perm_query_resp);
1177
0
    memcpy(active_component_key_perm_bitmap, bitmap_ptr,
1178
0
           resp->permission_bitmap_length);
1179
0
  }
1180
0
  if (pending_component_key_perm_bitmap != NULL) {
1181
0
    const uint8_t *bitmap_ptr =
1182
0
        msg->payload +
1183
0
        sizeof(struct nsm_code_auth_key_perm_query_resp) +
1184
0
        resp->permission_bitmap_length;
1185
0
    memcpy(pending_component_key_perm_bitmap, bitmap_ptr,
1186
0
           resp->permission_bitmap_length);
1187
0
  }
1188
0
  if (efuse_key_perm_bitmap != NULL) {
1189
0
    const uint8_t *bitmap_ptr =
1190
0
        msg->payload +
1191
0
        sizeof(struct nsm_code_auth_key_perm_query_resp) +
1192
0
        resp->permission_bitmap_length * 2u;
1193
0
    memcpy(efuse_key_perm_bitmap, bitmap_ptr,
1194
0
           resp->permission_bitmap_length);
1195
0
  }
1196
0
  if (pending_efuse_key_perm_bitmap != NULL) {
1197
0
    const uint8_t *bitmap_ptr =
1198
0
        msg->payload +
1199
0
        sizeof(struct nsm_code_auth_key_perm_query_resp) +
1200
0
        resp->permission_bitmap_length * 3u;
1201
0
    memcpy(pending_efuse_key_perm_bitmap, bitmap_ptr,
1202
0
           resp->permission_bitmap_length);
1203
0
  }
1204
1205
0
  return NSM_SW_SUCCESS;
1206
0
}
1207
1208
int encode_nsm_code_auth_key_perm_query_resp(
1209
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
1210
    uint16_t active_component_key_index, uint16_t pending_component_key_index,
1211
    uint8_t permission_bitmap_length, uint8_t *active_component_key_perm_bitmap,
1212
    uint8_t *pending_component_key_perm_bitmap, uint8_t *efuse_key_perm_bitmap,
1213
    uint8_t *pending_efuse_key_perm_bitmap, struct nsm_msg *msg)
1214
0
{
1215
0
  if (msg == NULL || (permission_bitmap_length != 0 &&
1216
0
          (active_component_key_perm_bitmap == NULL ||
1217
0
           pending_component_key_perm_bitmap == NULL ||
1218
0
           efuse_key_perm_bitmap == NULL ||
1219
0
           pending_efuse_key_perm_bitmap == NULL))) {
1220
0
    return NSM_SW_ERROR_NULL;
1221
0
  }
1222
1223
0
  struct nsm_header_info header = {0};
1224
0
  header.nsm_msg_type = NSM_RESPONSE;
1225
0
  header.instance_id = instance_id;
1226
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
1227
1228
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1229
0
  if (rc != NSM_SW_SUCCESS) {
1230
0
    return rc;
1231
0
  }
1232
1233
0
  if (cc != NSM_SUCCESS) {
1234
0
    return encode_reason_code(cc, reason_code,
1235
0
            NSM_FW_QUERY_CODE_AUTH_KEY_PERM, msg);
1236
0
  }
1237
1238
0
  struct nsm_code_auth_key_perm_query_resp *resp =
1239
0
      (struct nsm_code_auth_key_perm_query_resp *)msg->payload;
1240
0
  resp->hdr.command = NSM_FW_QUERY_CODE_AUTH_KEY_PERM;
1241
0
  resp->hdr.completion_code = cc;
1242
0
  resp->hdr.data_size =
1243
0
      htole16(sizeof(struct nsm_code_auth_key_perm_query_resp) -
1244
0
        NSM_RESPONSE_CONVENTION_LEN) +
1245
0
      permission_bitmap_length;
1246
0
  resp->active_component_key_index = active_component_key_index;
1247
0
  resp->pending_component_key_index = pending_component_key_index;
1248
0
  resp->permission_bitmap_length = permission_bitmap_length;
1249
0
  uint8_t *bitmap_ptr =
1250
0
      msg->payload + sizeof(struct nsm_code_auth_key_perm_query_resp);
1251
0
  memcpy(bitmap_ptr, active_component_key_perm_bitmap,
1252
0
         permission_bitmap_length);
1253
0
  bitmap_ptr += permission_bitmap_length;
1254
0
  memcpy(bitmap_ptr, pending_component_key_perm_bitmap,
1255
0
         permission_bitmap_length);
1256
0
  bitmap_ptr += permission_bitmap_length;
1257
0
  memcpy(bitmap_ptr, efuse_key_perm_bitmap, permission_bitmap_length);
1258
0
  bitmap_ptr += permission_bitmap_length;
1259
0
  memcpy(bitmap_ptr, pending_efuse_key_perm_bitmap,
1260
0
         permission_bitmap_length);
1261
1262
0
  return NSM_SW_SUCCESS;
1263
0
}
1264
1265
int decode_nsm_code_auth_key_perm_update_req(
1266
    const struct nsm_msg *msg, size_t msg_len,
1267
    enum nsm_code_auth_key_perm_request_type *request_type,
1268
    uint16_t *component_classification, uint16_t *component_identifier,
1269
    uint8_t *component_classification_index, uint64_t *nonce,
1270
    uint8_t *permission_bitmap_length, uint8_t *permission_bitmap)
1271
0
{
1272
0
  if (msg == NULL || request_type == NULL ||
1273
0
      component_classification == NULL || component_identifier == NULL ||
1274
0
      component_classification_index == NULL || nonce == NULL ||
1275
0
      permission_bitmap_length == NULL) {
1276
0
    return NSM_SW_ERROR_NULL;
1277
0
  }
1278
1279
0
  size_t expected_bitmap_length =
1280
0
      msg_len - sizeof(struct nsm_msg_hdr) -
1281
0
      sizeof(struct nsm_code_auth_key_perm_update_req);
1282
0
  struct nsm_code_auth_key_perm_update_req *req =
1283
0
      (struct nsm_code_auth_key_perm_update_req *)msg->payload;
1284
0
  if (expected_bitmap_length != req->permission_bitmap_length) {
1285
0
    return NSM_SW_ERROR_LENGTH;
1286
0
  }
1287
0
  if (req->request_type !=
1288
0
    NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_MOST_RESTRICTIVE_VALUE &&
1289
0
      req->request_type !=
1290
0
    NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_SPECIFIED_VALUE) {
1291
0
    return NSM_SW_ERROR_DATA;
1292
0
  }
1293
0
  *request_type = req->request_type;
1294
0
  *component_classification = req->component_classification;
1295
0
  *component_identifier = req->component_identifier;
1296
0
  *component_classification_index = req->component_classification_index;
1297
0
  *nonce = req->nonce;
1298
0
  *permission_bitmap_length = req->permission_bitmap_length;
1299
0
  if (permission_bitmap != NULL) {
1300
0
    const uint8_t *bitmap_ptr =
1301
0
        msg->payload +
1302
0
        sizeof(struct nsm_code_auth_key_perm_update_req);
1303
0
    memcpy(permission_bitmap, bitmap_ptr, expected_bitmap_length);
1304
0
  }
1305
1306
0
  return NSM_SW_SUCCESS;
1307
0
}
1308
1309
int encode_nsm_code_auth_key_perm_update_req(
1310
    uint8_t instance_id, enum nsm_code_auth_key_perm_request_type request_type,
1311
    uint16_t component_classification, uint16_t component_identifier,
1312
    uint8_t component_classification_index, uint64_t nonce,
1313
    uint8_t permission_bitmap_length, uint8_t *permission_bitmap,
1314
    struct nsm_msg *msg)
1315
0
{
1316
0
  if (msg == NULL) {
1317
0
    return NSM_SW_ERROR_NULL;
1318
0
  }
1319
0
  if (request_type !=
1320
0
    NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_MOST_RESTRICTIVE_VALUE &&
1321
0
      request_type !=
1322
0
    NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_SPECIFIED_VALUE) {
1323
0
    return NSM_SW_ERROR_DATA;
1324
0
  }
1325
0
  if (request_type ==
1326
0
    NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_MOST_RESTRICTIVE_VALUE &&
1327
0
      permission_bitmap_length != 0) {
1328
0
    return NSM_SW_ERROR_DATA;
1329
0
  }
1330
0
  if (request_type ==
1331
0
    NSM_CODE_AUTH_KEY_PERM_REQUEST_TYPE_SPECIFIED_VALUE &&
1332
0
      (permission_bitmap_length == 0 || permission_bitmap == NULL)) {
1333
0
    return NSM_SW_ERROR_DATA;
1334
0
  }
1335
1336
0
  struct nsm_header_info header = {0};
1337
0
  header.nsm_msg_type = NSM_REQUEST;
1338
0
  header.instance_id = instance_id;
1339
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
1340
1341
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1342
0
  if (rc != NSM_SUCCESS) {
1343
0
    return rc;
1344
0
  }
1345
1346
0
  struct nsm_code_auth_key_perm_update_req *req =
1347
0
      (struct nsm_code_auth_key_perm_update_req *)msg->payload;
1348
0
  req->hdr.command = NSM_FW_UPDATE_CODE_AUTH_KEY_PERM;
1349
0
  req->hdr.data_size =
1350
0
      htole16(sizeof(struct nsm_code_auth_key_perm_update_req) -
1351
0
        NSM_REQUEST_CONVENTION_LEN + permission_bitmap_length);
1352
0
  req->request_type = request_type;
1353
0
  req->component_classification = component_classification;
1354
0
  req->component_identifier = component_identifier;
1355
0
  req->component_classification_index = component_classification_index;
1356
0
  req->nonce = nonce;
1357
0
  req->permission_bitmap_length = permission_bitmap_length;
1358
0
  if (permission_bitmap_length != 0) {
1359
0
    uint8_t *bitmap_ptr =
1360
0
        msg->payload +
1361
0
        sizeof(struct nsm_code_auth_key_perm_update_req);
1362
0
    memcpy(bitmap_ptr, permission_bitmap, permission_bitmap_length);
1363
0
  }
1364
1365
0
  return NSM_SUCCESS;
1366
0
}
1367
1368
int decode_nsm_code_auth_key_perm_update_resp(const struct nsm_msg *msg,
1369
                size_t msg_len, uint8_t *cc,
1370
                uint16_t *reason_code,
1371
                uint32_t *update_method)
1372
0
{
1373
0
  if (msg == NULL || update_method == NULL) {
1374
0
    return NSM_SW_ERROR_NULL;
1375
0
  }
1376
1377
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1378
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1379
0
    return rc;
1380
0
  }
1381
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1382
0
        sizeof(struct nsm_code_auth_key_perm_update_resp)) {
1383
0
    return NSM_SW_ERROR_LENGTH;
1384
0
  }
1385
1386
0
  struct nsm_code_auth_key_perm_update_resp *resp =
1387
0
      (struct nsm_code_auth_key_perm_update_resp *)msg->payload;
1388
0
  if (resp->hdr.data_size <
1389
0
      sizeof(struct nsm_code_auth_key_perm_update_resp) -
1390
0
    NSM_RESPONSE_CONVENTION_LEN) {
1391
0
    return NSM_SW_ERROR_DATA;
1392
0
  }
1393
0
  *update_method = resp->update_method;
1394
1395
0
  return NSM_SW_SUCCESS;
1396
0
}
1397
1398
int encode_nsm_code_auth_key_perm_update_resp(uint8_t instance_id, uint8_t cc,
1399
                uint16_t reason_code,
1400
                uint32_t update_method,
1401
                struct nsm_msg *msg)
1402
0
{
1403
0
  if (msg == NULL) {
1404
0
    return NSM_SW_ERROR_NULL;
1405
0
  }
1406
1407
0
  struct nsm_header_info header = {0};
1408
0
  header.nsm_msg_type = NSM_RESPONSE;
1409
0
  header.instance_id = instance_id;
1410
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
1411
1412
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1413
0
  if (rc != NSM_SW_SUCCESS) {
1414
0
    return rc;
1415
0
  }
1416
1417
0
  if (cc != NSM_SUCCESS) {
1418
0
    return encode_reason_code(
1419
0
        cc, reason_code, NSM_FW_UPDATE_CODE_AUTH_KEY_PERM, msg);
1420
0
  }
1421
1422
0
  struct nsm_code_auth_key_perm_update_resp *resp =
1423
0
      (struct nsm_code_auth_key_perm_update_resp *)msg->payload;
1424
0
  resp->hdr.command = NSM_FW_UPDATE_CODE_AUTH_KEY_PERM;
1425
0
  resp->hdr.completion_code = cc;
1426
0
  resp->hdr.data_size =
1427
0
      htole16(sizeof(struct nsm_code_auth_key_perm_update_resp) -
1428
0
        NSM_RESPONSE_CONVENTION_LEN);
1429
0
  resp->update_method = update_method;
1430
1431
0
  return NSM_SW_SUCCESS;
1432
0
}
1433
1434
int encode_nsm_query_firmware_security_version_number_req(
1435
    uint8_t instance_id,
1436
    const struct nsm_firmware_security_version_number_req *fw_req,
1437
    struct nsm_msg *msg)
1438
0
{
1439
0
  if (msg == NULL) {
1440
0
    return NSM_SW_ERROR_NULL;
1441
0
  }
1442
0
  struct nsm_header_info header = {0};
1443
0
  header.nsm_msg_type = NSM_REQUEST;
1444
0
  header.instance_id = instance_id;
1445
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
1446
1447
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1448
0
  if (rc != NSM_SUCCESS) {
1449
0
    return rc;
1450
0
  }
1451
1452
0
  struct nsm_firmware_security_version_number_req_command *request =
1453
0
      (struct nsm_firmware_security_version_number_req_command *)
1454
0
    msg->payload;
1455
0
  request->hdr.command = NSM_FW_QUERY_MIN_SECURITY_VERSION_NUMBER;
1456
0
  request->hdr.data_size =
1457
0
      sizeof(struct nsm_firmware_security_version_number_req);
1458
0
  memcpy(&request->fq_req, fw_req,
1459
0
         sizeof(struct nsm_firmware_security_version_number_req));
1460
1461
0
  return NSM_SW_SUCCESS;
1462
0
}
1463
1464
int decode_nsm_query_firmware_security_version_number_req(
1465
    const struct nsm_msg *msg, size_t msg_len,
1466
    struct nsm_firmware_security_version_number_req *fw_req)
1467
0
{
1468
0
  if (msg == NULL || fw_req == NULL) {
1469
0
    return NSM_SW_ERROR_NULL;
1470
0
  }
1471
1472
0
  if (msg_len <
1473
0
      sizeof(struct nsm_msg_hdr) +
1474
0
    sizeof(
1475
0
        struct nsm_firmware_security_version_number_req_command)) {
1476
0
    return NSM_SW_ERROR_LENGTH;
1477
0
  }
1478
1479
0
  struct nsm_firmware_security_version_number_req_command *request =
1480
0
      (struct nsm_firmware_security_version_number_req_command *)
1481
0
    msg->payload;
1482
0
  if (request->hdr.data_size < sizeof(*fw_req)) {
1483
0
    return NSM_SW_ERROR_DATA;
1484
0
  }
1485
1486
0
  *fw_req = request->fq_req;
1487
1488
0
  return NSM_SW_SUCCESS;
1489
0
}
1490
1491
int encode_nsm_query_firmware_security_version_number_resp(
1492
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
1493
    struct nsm_firmware_security_version_number_resp *sec_info,
1494
    struct nsm_msg *msg)
1495
0
{
1496
0
  if (msg == NULL) {
1497
0
    return NSM_SW_ERROR_NULL;
1498
0
  }
1499
1500
0
  struct nsm_header_info header = {0};
1501
0
  header.nsm_msg_type = NSM_RESPONSE;
1502
0
  header.instance_id = instance_id;
1503
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
1504
1505
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1506
0
  if (rc != NSM_SW_SUCCESS) {
1507
0
    return rc;
1508
0
  }
1509
1510
0
  if (cc != NSM_SUCCESS) {
1511
0
    return encode_reason_code(
1512
0
        cc, reason_code, NSM_FW_QUERY_MIN_SECURITY_VERSION_NUMBER,
1513
0
        msg);
1514
0
  }
1515
1516
0
  struct nsm_firmware_security_version_number_resp_command *response =
1517
0
      (struct nsm_firmware_security_version_number_resp_command *)
1518
0
    msg->payload;
1519
0
  response->hdr.command = NSM_FW_QUERY_MIN_SECURITY_VERSION_NUMBER;
1520
0
  response->hdr.completion_code = cc;
1521
1522
0
  uint16_t msg_size =
1523
0
      sizeof(struct nsm_common_resp) +
1524
0
      sizeof(struct nsm_firmware_security_version_number_resp);
1525
1526
0
  response->hdr.data_size = htole16(msg_size);
1527
1528
0
  memcpy(&(response->sec_ver_resp), sec_info,
1529
0
         sizeof(struct nsm_firmware_security_version_number_resp));
1530
1531
0
  return NSM_SW_SUCCESS;
1532
0
}
1533
1534
int decode_nsm_query_firmware_security_version_number_resp(
1535
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
1536
    uint16_t *reason_code,
1537
    struct nsm_firmware_security_version_number_resp *sec_resp)
1538
0
{
1539
0
  if (msg == NULL || sec_resp == NULL) {
1540
0
    return NSM_SW_ERROR_NULL;
1541
0
  }
1542
1543
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1544
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1545
0
    return rc;
1546
0
  }
1547
1548
0
  if (msg_len <
1549
0
      sizeof(struct nsm_msg_hdr) +
1550
0
    sizeof(
1551
0
        struct nsm_firmware_security_version_number_resp_command)) {
1552
0
    return NSM_SW_ERROR_LENGTH;
1553
0
  }
1554
1555
0
  struct nsm_firmware_security_version_number_resp_command *resp =
1556
0
      (struct nsm_firmware_security_version_number_resp_command *)
1557
0
    msg->payload;
1558
1559
0
  memcpy(sec_resp, &(resp->sec_ver_resp),
1560
0
         sizeof(struct nsm_firmware_security_version_number_resp));
1561
1562
0
  return NSM_SW_SUCCESS;
1563
0
}
1564
1565
int encode_nsm_firmware_update_sec_ver_req(
1566
    uint8_t instance_id,
1567
    const struct nsm_firmware_update_min_sec_ver_req *fw_req,
1568
    struct nsm_msg *msg)
1569
0
{
1570
0
  if (msg == NULL) {
1571
0
    return NSM_SW_ERROR_NULL;
1572
0
  }
1573
0
  struct nsm_header_info header = {0};
1574
0
  header.nsm_msg_type = NSM_REQUEST;
1575
0
  header.instance_id = instance_id;
1576
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
1577
1578
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1579
0
  if (rc != NSM_SUCCESS) {
1580
0
    return rc;
1581
0
  }
1582
1583
0
  struct nsm_firmware_update_min_sec_ver_req_command *request =
1584
0
      (struct nsm_firmware_update_min_sec_ver_req_command *)msg->payload;
1585
0
  request->hdr.command = NSM_FW_UPDATE_MIN_SECURITY_VERSION_NUMBER;
1586
0
  request->hdr.data_size =
1587
0
      sizeof(struct nsm_firmware_update_min_sec_ver_req);
1588
0
  memcpy(&request->ver_update_req, fw_req,
1589
0
         sizeof(struct nsm_firmware_update_min_sec_ver_req));
1590
1591
0
  return NSM_SW_SUCCESS;
1592
0
}
1593
1594
int decode_nsm_firmware_update_sec_ver_req(
1595
    const struct nsm_msg *msg, size_t msg_len,
1596
    struct nsm_firmware_update_min_sec_ver_req *fw_req)
1597
0
{
1598
0
  if (msg == NULL || fw_req == NULL) {
1599
0
    return NSM_SW_ERROR_NULL;
1600
0
  }
1601
1602
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1603
0
        sizeof(struct nsm_firmware_update_min_sec_ver_req)) {
1604
0
    return NSM_SW_ERROR_LENGTH;
1605
0
  }
1606
1607
0
  struct nsm_firmware_update_min_sec_ver_req_command *request =
1608
0
      (struct nsm_firmware_update_min_sec_ver_req_command *)msg->payload;
1609
0
  if (request->hdr.data_size < sizeof(*fw_req)) {
1610
0
    return NSM_SW_ERROR_DATA;
1611
0
  }
1612
1613
0
  *fw_req = request->ver_update_req;
1614
1615
0
  return NSM_SW_SUCCESS;
1616
0
}
1617
1618
int encode_nsm_firmware_update_sec_ver_resp(
1619
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
1620
    struct nsm_firmware_update_min_sec_ver_resp *sec_resp, struct nsm_msg *msg)
1621
0
{
1622
0
  if (msg == NULL) {
1623
0
    return NSM_SW_ERROR_NULL;
1624
0
  }
1625
1626
0
  struct nsm_header_info header = {0};
1627
0
  header.nsm_msg_type = NSM_RESPONSE;
1628
0
  header.instance_id = instance_id;
1629
0
  header.nvidia_msg_type = NSM_TYPE_FIRMWARE;
1630
1631
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1632
0
  if (rc != NSM_SW_SUCCESS) {
1633
0
    return rc;
1634
0
  }
1635
1636
0
  if (cc != NSM_SUCCESS) {
1637
0
    return encode_reason_code(
1638
0
        cc, reason_code, NSM_FW_UPDATE_MIN_SECURITY_VERSION_NUMBER,
1639
0
        msg);
1640
0
  }
1641
1642
0
  struct nsm_firmware_update_min_sec_ver_resp_command *response =
1643
0
      (struct nsm_firmware_update_min_sec_ver_resp_command *)msg->payload;
1644
0
  response->hdr.command = NSM_FW_UPDATE_MIN_SECURITY_VERSION_NUMBER;
1645
0
  response->hdr.completion_code = cc;
1646
1647
0
  uint16_t msg_size = sizeof(struct nsm_common_resp) +
1648
0
          sizeof(struct nsm_firmware_update_min_sec_ver_resp);
1649
1650
0
  response->hdr.data_size = htole16(msg_size);
1651
1652
0
  memcpy(&(response->sec_ver_resp), sec_resp,
1653
0
         sizeof(struct nsm_firmware_update_min_sec_ver_resp));
1654
1655
0
  return NSM_SW_SUCCESS;
1656
0
}
1657
1658
int decode_nsm_firmware_update_sec_ver_resp(
1659
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
1660
    uint16_t *reason_code,
1661
    struct nsm_firmware_update_min_sec_ver_resp *sec_resp)
1662
0
{
1663
0
  if (msg == NULL || sec_resp == NULL) {
1664
0
    return NSM_SW_ERROR_NULL;
1665
0
  }
1666
1667
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1668
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1669
0
    return rc;
1670
0
  }
1671
1672
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1673
0
        sizeof(struct nsm_firmware_update_min_sec_ver_resp)) {
1674
0
    return NSM_SW_ERROR_LENGTH;
1675
0
  }
1676
1677
0
  struct nsm_firmware_update_min_sec_ver_resp_command *resp =
1678
0
      (struct nsm_firmware_update_min_sec_ver_resp_command *)msg->payload;
1679
1680
0
  memcpy(sec_resp, &(resp->sec_ver_resp),
1681
0
         sizeof(struct nsm_firmware_update_min_sec_ver_resp));
1682
1683
0
  return NSM_SW_SUCCESS;
1684
0
}