1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2009-2018 Solarflare Communications Inc.
14 static const efx_nvram_ops_t __efx_nvram_siena_ops = {
16 siena_nvram_test, /* envo_test */
17 #endif /* EFSYS_OPT_DIAG */
18 siena_nvram_type_to_partn, /* envo_type_to_partn */
19 siena_nvram_partn_size, /* envo_partn_size */
20 siena_nvram_partn_rw_start, /* envo_partn_rw_start */
21 siena_nvram_partn_read, /* envo_partn_read */
22 siena_nvram_partn_read, /* envo_partn_read_backup */
23 siena_nvram_partn_erase, /* envo_partn_erase */
24 siena_nvram_partn_write, /* envo_partn_write */
25 siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */
26 siena_nvram_partn_get_version, /* envo_partn_get_version */
27 siena_nvram_partn_set_version, /* envo_partn_set_version */
28 NULL, /* envo_partn_validate */
31 #endif /* EFSYS_OPT_SIENA */
33 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
35 static const efx_nvram_ops_t __efx_nvram_ef10_ops = {
37 ef10_nvram_test, /* envo_test */
38 #endif /* EFSYS_OPT_DIAG */
39 ef10_nvram_type_to_partn, /* envo_type_to_partn */
40 ef10_nvram_partn_size, /* envo_partn_size */
41 ef10_nvram_partn_rw_start, /* envo_partn_rw_start */
42 ef10_nvram_partn_read, /* envo_partn_read */
43 ef10_nvram_partn_read_backup, /* envo_partn_read_backup */
44 ef10_nvram_partn_erase, /* envo_partn_erase */
45 ef10_nvram_partn_write, /* envo_partn_write */
46 ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */
47 ef10_nvram_partn_get_version, /* envo_partn_get_version */
48 ef10_nvram_partn_set_version, /* envo_partn_set_version */
49 ef10_nvram_buffer_validate, /* envo_buffer_validate */
52 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
54 __checkReturn efx_rc_t
58 const efx_nvram_ops_t *envop;
61 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
62 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
63 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
65 switch (enp->en_family) {
67 case EFX_FAMILY_SIENA:
68 envop = &__efx_nvram_siena_ops;
70 #endif /* EFSYS_OPT_SIENA */
72 #if EFSYS_OPT_HUNTINGTON
73 case EFX_FAMILY_HUNTINGTON:
74 envop = &__efx_nvram_ef10_ops;
76 #endif /* EFSYS_OPT_HUNTINGTON */
79 case EFX_FAMILY_MEDFORD:
80 envop = &__efx_nvram_ef10_ops;
82 #endif /* EFSYS_OPT_MEDFORD */
90 enp->en_envop = envop;
91 enp->en_mod_flags |= EFX_MOD_NVRAM;
93 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
98 EFSYS_PROBE1(fail1, efx_rc_t, rc);
105 __checkReturn efx_rc_t
109 const efx_nvram_ops_t *envop = enp->en_envop;
112 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
113 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
115 if ((rc = envop->envo_test(enp)) != 0)
121 EFSYS_PROBE1(fail1, efx_rc_t, rc);
126 #endif /* EFSYS_OPT_DIAG */
128 __checkReturn efx_rc_t
131 __in efx_nvram_type_t type,
134 const efx_nvram_ops_t *envop = enp->en_envop;
138 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
139 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
141 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
144 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
152 EFSYS_PROBE1(fail1, efx_rc_t, rc);
158 __checkReturn efx_rc_t
159 efx_nvram_get_version(
161 __in efx_nvram_type_t type,
162 __out uint32_t *subtypep,
163 __out_ecount(4) uint16_t version[4])
165 const efx_nvram_ops_t *envop = enp->en_envop;
169 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
170 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
171 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
173 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
176 if ((rc = envop->envo_partn_get_version(enp, partn,
177 subtypep, version)) != 0)
185 EFSYS_PROBE1(fail1, efx_rc_t, rc);
190 __checkReturn efx_rc_t
193 __in efx_nvram_type_t type,
194 __out_opt size_t *chunk_sizep)
196 const efx_nvram_ops_t *envop = enp->en_envop;
200 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
201 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
203 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
206 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
208 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
211 enp->en_nvram_partn_locked = partn;
218 EFSYS_PROBE1(fail1, efx_rc_t, rc);
223 __checkReturn efx_rc_t
224 efx_nvram_read_chunk(
226 __in efx_nvram_type_t type,
227 __in unsigned int offset,
228 __out_bcount(size) caddr_t data,
231 const efx_nvram_ops_t *envop = enp->en_envop;
235 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
236 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
238 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
241 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
243 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
251 EFSYS_PROBE1(fail1, efx_rc_t, rc);
257 * Read from the backup (writeable) store of an A/B partition.
258 * For non A/B partitions, there is only a single store, and so this
259 * function has the same behaviour as efx_nvram_read_chunk().
261 __checkReturn efx_rc_t
262 efx_nvram_read_backup(
264 __in efx_nvram_type_t type,
265 __in unsigned int offset,
266 __out_bcount(size) caddr_t data,
269 const efx_nvram_ops_t *envop = enp->en_envop;
273 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
274 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
276 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
279 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
281 if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
290 EFSYS_PROBE1(fail1, efx_rc_t, rc);
295 __checkReturn efx_rc_t
298 __in efx_nvram_type_t type)
300 const efx_nvram_ops_t *envop = enp->en_envop;
301 unsigned int offset = 0;
306 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
307 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
309 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
312 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
314 if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
317 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
327 EFSYS_PROBE1(fail1, efx_rc_t, rc);
332 __checkReturn efx_rc_t
333 efx_nvram_write_chunk(
335 __in efx_nvram_type_t type,
336 __in unsigned int offset,
337 __in_bcount(size) caddr_t data,
340 const efx_nvram_ops_t *envop = enp->en_envop;
344 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
345 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
347 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
350 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
352 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
360 EFSYS_PROBE1(fail1, efx_rc_t, rc);
365 __checkReturn efx_rc_t
368 __in efx_nvram_type_t type,
369 __out_opt uint32_t *verify_resultp)
371 const efx_nvram_ops_t *envop = enp->en_envop;
373 uint32_t verify_result = 0;
376 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
377 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
379 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
382 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
384 if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0)
387 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
389 if (verify_resultp != NULL)
390 *verify_resultp = verify_result;
396 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
399 EFSYS_PROBE1(fail1, efx_rc_t, rc);
401 /* Always report verification result */
402 if (verify_resultp != NULL)
403 *verify_resultp = verify_result;
408 __checkReturn efx_rc_t
409 efx_nvram_set_version(
411 __in efx_nvram_type_t type,
412 __in_ecount(4) uint16_t version[4])
414 const efx_nvram_ops_t *envop = enp->en_envop;
418 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
419 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
420 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
422 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
426 * The Siena implementation of envo_set_version() will attempt to
427 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition.
428 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
430 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
432 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
440 EFSYS_PROBE1(fail1, efx_rc_t, rc);
445 /* Validate buffer contents (before writing to flash) */
446 __checkReturn efx_rc_t
449 __in efx_nvram_type_t type,
450 __in_bcount(partn_size) caddr_t partn_data,
451 __in size_t partn_size)
453 const efx_nvram_ops_t *envop = enp->en_envop;
457 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
458 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
459 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
461 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
464 if (envop->envo_buffer_validate != NULL) {
465 if ((rc = envop->envo_buffer_validate(enp, partn,
466 partn_data, partn_size)) != 0)
475 EFSYS_PROBE1(fail1, efx_rc_t, rc);
485 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
486 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
487 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
489 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
491 enp->en_envop = NULL;
492 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
495 #endif /* EFSYS_OPT_NVRAM */
497 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
500 * Internal MCDI request handling
503 __checkReturn efx_rc_t
504 efx_mcdi_nvram_partitions(
506 __out_bcount(size) caddr_t data,
508 __out unsigned int *npartnp)
511 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
512 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
516 (void) memset(payload, 0, sizeof (payload));
517 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
518 req.emr_in_buf = payload;
519 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
520 req.emr_out_buf = payload;
521 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
523 efx_mcdi_execute(enp, &req);
525 if (req.emr_rc != 0) {
530 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
534 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
536 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
541 if (size < npartn * sizeof (uint32_t)) {
549 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
550 (npartn * sizeof (uint32_t)));
559 EFSYS_PROBE1(fail1, efx_rc_t, rc);
564 __checkReturn efx_rc_t
565 efx_mcdi_nvram_metadata(
568 __out uint32_t *subtypep,
569 __out_ecount(4) uint16_t version[4],
570 __out_bcount_opt(size) char *descp,
574 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
575 MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
578 (void) memset(payload, 0, sizeof (payload));
579 req.emr_cmd = MC_CMD_NVRAM_METADATA;
580 req.emr_in_buf = payload;
581 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
582 req.emr_out_buf = payload;
583 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
585 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
587 efx_mcdi_execute_quiet(enp, &req);
589 if (req.emr_rc != 0) {
594 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
599 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
600 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
601 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
606 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
607 NVRAM_METADATA_OUT_VERSION_VALID)) {
608 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
609 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
610 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
611 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
613 version[0] = version[1] = version[2] = version[3] = 0;
616 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
617 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
618 /* Return optional descrition string */
619 if ((descp != NULL) && (size > 0)) {
623 desclen = (req.emr_out_length_used
624 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
626 EFSYS_ASSERT3U(desclen, <=,
627 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
629 if (size < desclen) {
634 memcpy(descp, MCDI_OUT2(req, char,
635 NVRAM_METADATA_OUT_DESCRIPTION),
638 /* Ensure string is NUL terminated */
639 descp[desclen] = '\0';
650 EFSYS_PROBE1(fail1, efx_rc_t, rc);
655 __checkReturn efx_rc_t
659 __out_opt size_t *sizep,
660 __out_opt uint32_t *addressp,
661 __out_opt uint32_t *erase_sizep,
662 __out_opt uint32_t *write_sizep)
664 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
665 MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
669 (void) memset(payload, 0, sizeof (payload));
670 req.emr_cmd = MC_CMD_NVRAM_INFO;
671 req.emr_in_buf = payload;
672 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
673 req.emr_out_buf = payload;
674 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
676 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
678 efx_mcdi_execute_quiet(enp, &req);
680 if (req.emr_rc != 0) {
685 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
691 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
694 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
697 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
701 (req.emr_out_length_used <
702 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
703 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
711 EFSYS_PROBE1(fail1, efx_rc_t, rc);
717 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
718 * NVRAM updates. Older firmware will ignore the flags field in the request.
720 __checkReturn efx_rc_t
721 efx_mcdi_nvram_update_start(
725 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
726 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
730 (void) memset(payload, 0, sizeof (payload));
731 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
732 req.emr_in_buf = payload;
733 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
734 req.emr_out_buf = payload;
735 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
737 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
739 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
740 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
742 efx_mcdi_execute(enp, &req);
744 if (req.emr_rc != 0) {
752 EFSYS_PROBE1(fail1, efx_rc_t, rc);
757 __checkReturn efx_rc_t
761 __in uint32_t offset,
762 __out_bcount(size) caddr_t data,
767 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
768 MC_CMD_NVRAM_READ_OUT_LENMAX)];
771 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
776 (void) memset(payload, 0, sizeof (payload));
777 req.emr_cmd = MC_CMD_NVRAM_READ;
778 req.emr_in_buf = payload;
779 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
780 req.emr_out_buf = payload;
781 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
783 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
784 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
785 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
786 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
788 efx_mcdi_execute(enp, &req);
790 if (req.emr_rc != 0) {
795 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
801 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
809 EFSYS_PROBE1(fail1, efx_rc_t, rc);
814 __checkReturn efx_rc_t
815 efx_mcdi_nvram_erase(
818 __in uint32_t offset,
822 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
823 MC_CMD_NVRAM_ERASE_OUT_LEN)];
826 (void) memset(payload, 0, sizeof (payload));
827 req.emr_cmd = MC_CMD_NVRAM_ERASE;
828 req.emr_in_buf = payload;
829 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
830 req.emr_out_buf = payload;
831 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
833 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
834 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
835 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
837 efx_mcdi_execute(enp, &req);
839 if (req.emr_rc != 0) {
847 EFSYS_PROBE1(fail1, efx_rc_t, rc);
853 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
854 * Sienna and EF10 based boards. However EF10 based boards support the use
855 * of this command with payloads up to the maximum MCDI V2 payload length.
857 __checkReturn efx_rc_t
858 efx_mcdi_nvram_write(
861 __in uint32_t offset,
862 __out_bcount(size) caddr_t data,
866 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1,
867 MCDI_CTL_SDU_LEN_MAX_V2)];
869 size_t max_data_size;
871 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length
872 - MC_CMD_NVRAM_WRITE_IN_LEN(0);
873 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0);
874 EFSYS_ASSERT3U(max_data_size, <,
875 enp->en_nic_cfg.enc_mcdi_max_payload_length);
877 if (size > max_data_size) {
882 (void) memset(payload, 0, sizeof (payload));
883 req.emr_cmd = MC_CMD_NVRAM_WRITE;
884 req.emr_in_buf = payload;
885 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
886 req.emr_out_buf = payload;
887 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
889 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
890 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
891 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
893 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
896 efx_mcdi_execute(enp, &req);
898 if (req.emr_rc != 0) {
908 EFSYS_PROBE1(fail1, efx_rc_t, rc);
915 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
916 * NVRAM updates. Older firmware will ignore the flags field in the request.
918 __checkReturn efx_rc_t
919 efx_mcdi_nvram_update_finish(
922 __in boolean_t reboot,
923 __out_opt uint32_t *verify_resultp)
925 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
927 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
928 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)];
929 uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
932 (void) memset(payload, 0, sizeof (payload));
933 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
934 req.emr_in_buf = payload;
935 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
936 req.emr_out_buf = payload;
937 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
939 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
940 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
942 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
943 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
945 efx_mcdi_execute(enp, &req);
947 if (req.emr_rc != 0) {
952 if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
953 verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
954 if (encp->enc_nvram_update_verify_result_supported) {
955 /* Result of update verification is missing */
961 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
964 if ((encp->enc_nvram_update_verify_result_supported) &&
965 (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) {
966 /* Update verification failed */
971 if (verify_resultp != NULL)
972 *verify_resultp = verify_result;
981 EFSYS_PROBE1(fail1, efx_rc_t, rc);
983 /* Always report verification result */
984 if (verify_resultp != NULL)
985 *verify_resultp = verify_result;
992 __checkReturn efx_rc_t
998 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
999 MC_CMD_NVRAM_TEST_OUT_LEN)];
1003 (void) memset(payload, 0, sizeof (payload));
1004 req.emr_cmd = MC_CMD_NVRAM_TEST;
1005 req.emr_in_buf = payload;
1006 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1007 req.emr_out_buf = payload;
1008 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1010 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1012 efx_mcdi_execute(enp, &req);
1014 if (req.emr_rc != 0) {
1019 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1024 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1025 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1027 EFSYS_PROBE1(nvram_test_failure, int, partn);
1040 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1045 #endif /* EFSYS_OPT_DIAG */
1048 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */