1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2021 Xilinx, Inc.
4 * Copyright(c) 2009-2019 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_info, /* envo_partn_info */
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 */
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_info, /* envo_partn_info */
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 /* EFX_OPTS_EF10() */
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 */
84 #if EFSYS_OPT_MEDFORD2
85 case EFX_FAMILY_MEDFORD2:
86 envop = &__efx_nvram_ef10_ops;
88 #endif /* EFSYS_OPT_MEDFORD2 */
96 enp->en_envop = envop;
97 enp->en_mod_flags |= EFX_MOD_NVRAM;
99 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
104 EFSYS_PROBE1(fail1, efx_rc_t, rc);
111 __checkReturn efx_rc_t
115 const efx_nvram_ops_t *envop = enp->en_envop;
118 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
119 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
121 if ((rc = envop->envo_test(enp)) != 0)
127 EFSYS_PROBE1(fail1, efx_rc_t, rc);
132 #endif /* EFSYS_OPT_DIAG */
134 __checkReturn efx_rc_t
137 __in efx_nvram_type_t type,
140 const efx_nvram_ops_t *envop = enp->en_envop;
141 efx_nvram_info_t eni = { 0 };
145 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
146 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
148 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
151 if ((rc = envop->envo_partn_info(enp, partn, &eni)) != 0)
154 *sizep = eni.eni_partn_size;
161 EFSYS_PROBE1(fail1, efx_rc_t, rc);
167 extern __checkReturn efx_rc_t
170 __in efx_nvram_type_t type,
171 __out efx_nvram_info_t *enip)
173 const efx_nvram_ops_t *envop = enp->en_envop;
177 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
178 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
180 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
183 if ((rc = envop->envo_partn_info(enp, partn, enip)) != 0)
191 EFSYS_PROBE1(fail1, efx_rc_t, rc);
197 __checkReturn efx_rc_t
198 efx_nvram_get_version(
200 __in efx_nvram_type_t type,
201 __out uint32_t *subtypep,
202 __out_ecount(4) uint16_t version[4])
204 const efx_nvram_ops_t *envop = enp->en_envop;
208 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
209 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
210 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
212 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
215 if ((rc = envop->envo_partn_get_version(enp, partn,
216 subtypep, version)) != 0)
224 EFSYS_PROBE1(fail1, efx_rc_t, rc);
229 __checkReturn efx_rc_t
232 __in efx_nvram_type_t type,
233 __out_opt size_t *chunk_sizep)
235 const efx_nvram_ops_t *envop = enp->en_envop;
239 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
240 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
242 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
245 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
247 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
250 enp->en_nvram_partn_locked = partn;
257 EFSYS_PROBE1(fail1, efx_rc_t, rc);
262 __checkReturn efx_rc_t
263 efx_nvram_read_chunk(
265 __in efx_nvram_type_t type,
266 __in unsigned int offset,
267 __out_bcount(size) caddr_t data,
270 const efx_nvram_ops_t *envop = enp->en_envop;
274 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
275 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
277 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
280 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
282 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
290 EFSYS_PROBE1(fail1, efx_rc_t, rc);
296 * Read from the backup (writeable) store of an A/B partition.
297 * For non A/B partitions, there is only a single store, and so this
298 * function has the same behaviour as efx_nvram_read_chunk().
300 __checkReturn efx_rc_t
301 efx_nvram_read_backup(
303 __in efx_nvram_type_t type,
304 __in unsigned int offset,
305 __out_bcount(size) caddr_t data,
308 const efx_nvram_ops_t *envop = enp->en_envop;
312 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
315 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
318 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
320 if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
329 EFSYS_PROBE1(fail1, efx_rc_t, rc);
334 __checkReturn efx_rc_t
337 __in efx_nvram_type_t type)
339 const efx_nvram_ops_t *envop = enp->en_envop;
340 unsigned int offset = 0;
341 efx_nvram_info_t eni = { 0 };
345 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
346 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
348 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
351 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
353 if ((rc = envop->envo_partn_info(enp, partn, &eni)) != 0)
356 if ((rc = envop->envo_partn_erase(enp, partn, offset,
357 eni.eni_partn_size)) != 0)
367 EFSYS_PROBE1(fail1, efx_rc_t, rc);
372 __checkReturn efx_rc_t
373 efx_nvram_write_chunk(
375 __in efx_nvram_type_t type,
376 __in unsigned int offset,
377 __in_bcount(size) caddr_t data,
380 const efx_nvram_ops_t *envop = enp->en_envop;
384 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
385 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
387 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
390 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
392 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
400 EFSYS_PROBE1(fail1, efx_rc_t, rc);
405 __checkReturn efx_rc_t
408 __in efx_nvram_type_t type,
409 __out_opt uint32_t *verify_resultp)
411 const efx_nvram_ops_t *envop = enp->en_envop;
413 uint32_t verify_result = 0;
416 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
417 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
419 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
422 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
424 if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0)
427 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
429 if (verify_resultp != NULL)
430 *verify_resultp = verify_result;
436 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
439 EFSYS_PROBE1(fail1, efx_rc_t, rc);
441 /* Always report verification result */
442 if (verify_resultp != NULL)
443 *verify_resultp = verify_result;
448 __checkReturn efx_rc_t
449 efx_nvram_set_version(
451 __in efx_nvram_type_t type,
452 __in_ecount(4) uint16_t version[4])
454 const efx_nvram_ops_t *envop = enp->en_envop;
458 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
459 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
460 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
462 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
466 * The Siena implementation of envo_set_version() will attempt to
467 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition.
468 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
470 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
472 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
480 EFSYS_PROBE1(fail1, efx_rc_t, rc);
485 /* Validate buffer contents (before writing to flash) */
486 __checkReturn efx_rc_t
489 __in efx_nvram_type_t type,
490 __in_bcount(partn_size) caddr_t partn_data,
491 __in size_t partn_size)
493 const efx_nvram_ops_t *envop = enp->en_envop;
497 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
498 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
499 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
501 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
504 if (envop->envo_buffer_validate != NULL) {
505 if ((rc = envop->envo_buffer_validate(partn,
506 partn_data, partn_size)) != 0)
515 EFSYS_PROBE1(fail1, efx_rc_t, rc);
525 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
526 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
527 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
529 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
531 enp->en_envop = NULL;
532 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
535 #endif /* EFSYS_OPT_NVRAM */
537 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
540 * Internal MCDI request handling
543 __checkReturn efx_rc_t
544 efx_mcdi_nvram_partitions(
546 __out_bcount(size) caddr_t data,
548 __out unsigned int *npartnp)
551 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_PARTITIONS_IN_LEN,
552 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX);
556 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
557 req.emr_in_buf = payload;
558 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
559 req.emr_out_buf = payload;
560 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
562 efx_mcdi_execute(enp, &req);
564 if (req.emr_rc != 0) {
569 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
573 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
575 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
580 if (size < npartn * sizeof (uint32_t)) {
588 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
589 (npartn * sizeof (uint32_t)));
598 EFSYS_PROBE1(fail1, efx_rc_t, rc);
603 __checkReturn efx_rc_t
604 efx_mcdi_nvram_metadata(
607 __out uint32_t *subtypep,
608 __out_ecount(4) uint16_t version[4],
609 __out_bcount_opt(size) char *descp,
613 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_METADATA_IN_LEN,
614 MC_CMD_NVRAM_METADATA_OUT_LENMAX);
617 req.emr_cmd = MC_CMD_NVRAM_METADATA;
618 req.emr_in_buf = payload;
619 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
620 req.emr_out_buf = payload;
621 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
623 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
625 efx_mcdi_execute_quiet(enp, &req);
627 if (req.emr_rc != 0) {
632 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
637 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
638 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
639 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
644 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
645 NVRAM_METADATA_OUT_VERSION_VALID)) {
646 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
647 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
648 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
649 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
651 version[0] = version[1] = version[2] = version[3] = 0;
654 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
655 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
656 /* Return optional descrition string */
657 if ((descp != NULL) && (size > 0)) {
661 desclen = (req.emr_out_length_used
662 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
664 EFSYS_ASSERT3U(desclen, <=,
665 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
667 if (size < desclen) {
672 memcpy(descp, MCDI_OUT2(req, char,
673 NVRAM_METADATA_OUT_DESCRIPTION),
676 /* Ensure string is NUL terminated */
677 descp[desclen] = '\0';
688 EFSYS_PROBE1(fail1, efx_rc_t, rc);
693 __checkReturn efx_rc_t
697 __out efx_nvram_info_t *enip)
699 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_INFO_IN_LEN,
700 MC_CMD_NVRAM_INFO_V2_OUT_LEN);
704 req.emr_cmd = MC_CMD_NVRAM_INFO;
705 req.emr_in_buf = payload;
706 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
707 req.emr_out_buf = payload;
708 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
710 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
712 efx_mcdi_execute_quiet(enp, &req);
714 if (req.emr_rc != 0) {
719 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
724 enip->eni_partn_size = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
726 enip->eni_address = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
728 enip->eni_erase_size = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
730 enip->eni_write_size =
731 (req.emr_out_length_used <
732 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
733 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
737 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_INFO_OUT_FLAGS,
738 NVRAM_INFO_OUT_PROTECTED))
739 enip->eni_flags |= EFX_NVRAM_FLAG_READ_ONLY;
741 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_INFO_OUT_FLAGS,
742 NVRAM_INFO_OUT_READ_ONLY))
743 enip->eni_flags |= EFX_NVRAM_FLAG_READ_ONLY;
750 EFSYS_PROBE1(fail1, efx_rc_t, rc);
756 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
757 * NVRAM updates. Older firmware will ignore the flags field in the request.
759 __checkReturn efx_rc_t
760 efx_mcdi_nvram_update_start(
764 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
765 MC_CMD_NVRAM_UPDATE_START_OUT_LEN);
769 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
770 req.emr_in_buf = payload;
771 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
772 req.emr_out_buf = payload;
773 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
775 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
777 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
778 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
780 efx_mcdi_execute(enp, &req);
782 if (req.emr_rc != 0) {
790 EFSYS_PROBE1(fail1, efx_rc_t, rc);
795 __checkReturn efx_rc_t
799 __in uint32_t offset,
800 __out_bcount(size) caddr_t data,
805 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_READ_IN_V2_LEN,
806 MC_CMD_NVRAM_READ_OUT_LENMAX);
809 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
814 req.emr_cmd = MC_CMD_NVRAM_READ;
815 req.emr_in_buf = payload;
816 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
817 req.emr_out_buf = payload;
818 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
820 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
821 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
822 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
823 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
825 efx_mcdi_execute(enp, &req);
827 if (req.emr_rc != 0) {
832 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
838 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
846 EFSYS_PROBE1(fail1, efx_rc_t, rc);
851 __checkReturn efx_rc_t
852 efx_mcdi_nvram_erase(
855 __in uint32_t offset,
859 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_ERASE_IN_LEN,
860 MC_CMD_NVRAM_ERASE_OUT_LEN);
863 req.emr_cmd = MC_CMD_NVRAM_ERASE;
864 req.emr_in_buf = payload;
865 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
866 req.emr_out_buf = payload;
867 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
869 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
870 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
871 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
873 efx_mcdi_execute(enp, &req);
875 if (req.emr_rc != 0) {
883 EFSYS_PROBE1(fail1, efx_rc_t, rc);
889 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
890 * Sienna and EF10 based boards. However EF10 based boards support the use
891 * of this command with payloads up to the maximum MCDI V2 payload length.
893 __checkReturn efx_rc_t
894 efx_mcdi_nvram_write(
897 __in uint32_t offset,
898 __in_bcount(size) caddr_t data,
904 size_t max_data_size;
905 size_t payload_len = enp->en_nic_cfg.enc_mcdi_max_payload_length;
907 max_data_size = payload_len - MC_CMD_NVRAM_WRITE_IN_LEN(0);
908 EFSYS_ASSERT3U(payload_len, >, 0);
909 EFSYS_ASSERT3U(max_data_size, <, payload_len);
911 if (size > max_data_size) {
916 EFSYS_KMEM_ALLOC(enp->en_esip, payload_len, payload);
917 if (payload == NULL) {
922 (void) memset(payload, 0, payload_len);
923 req.emr_cmd = MC_CMD_NVRAM_WRITE;
924 req.emr_in_buf = payload;
925 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
926 req.emr_out_buf = payload;
927 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
929 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
930 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
931 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
933 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
936 efx_mcdi_execute(enp, &req);
938 if (req.emr_rc != 0) {
943 EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
949 EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
953 EFSYS_PROBE1(fail1, efx_rc_t, rc);
960 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
961 * NVRAM updates. Older firmware will ignore the flags field in the request.
963 __checkReturn efx_rc_t
964 efx_mcdi_nvram_update_finish(
967 __in boolean_t reboot,
969 __out_opt uint32_t *verify_resultp)
971 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
973 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
974 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN);
975 uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
978 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
979 req.emr_in_buf = payload;
980 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
981 req.emr_out_buf = payload;
982 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
984 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
985 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
987 if (!encp->enc_nvram_update_poll_verify_result_supported) {
988 flags &= ~EFX_NVRAM_UPDATE_FLAGS_BACKGROUND;
989 flags &= ~EFX_NVRAM_UPDATE_FLAGS_POLL;
992 MCDI_IN_POPULATE_DWORD_3(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
993 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT,
995 NVRAM_UPDATE_FINISH_V2_IN_FLAG_RUN_IN_BACKGROUND,
996 (flags & EFX_NVRAM_UPDATE_FLAGS_BACKGROUND) ? 1 : 0,
997 NVRAM_UPDATE_FINISH_V2_IN_FLAG_POLL_VERIFY_RESULT,
998 (flags & EFX_NVRAM_UPDATE_FLAGS_POLL) ? 1 : 0
1001 efx_mcdi_execute(enp, &req);
1003 if (req.emr_rc != 0) {
1008 if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
1009 verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
1010 if (encp->enc_nvram_update_verify_result_supported) {
1011 /* Result of update verification is missing */
1017 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
1020 if (encp->enc_nvram_update_verify_result_supported) {
1021 if ((verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) &&
1022 (verify_result != MC_CMD_NVRAM_VERIFY_RC_PENDING)) {
1023 /* Update verification failed */
1029 if (verify_resultp != NULL)
1030 *verify_resultp = verify_result;
1039 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1041 /* Always report verification result */
1042 if (verify_resultp != NULL)
1043 *verify_resultp = verify_result;
1050 __checkReturn efx_rc_t
1051 efx_mcdi_nvram_test(
1052 __in efx_nic_t *enp,
1053 __in uint32_t partn)
1056 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_TEST_IN_LEN,
1057 MC_CMD_NVRAM_TEST_OUT_LEN);
1061 req.emr_cmd = MC_CMD_NVRAM_TEST;
1062 req.emr_in_buf = payload;
1063 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1064 req.emr_out_buf = payload;
1065 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1067 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1069 efx_mcdi_execute(enp, &req);
1071 if (req.emr_rc != 0) {
1076 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1081 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1082 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1084 EFSYS_PROBE1(nvram_test_failure, int, partn);
1097 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1102 #endif /* EFSYS_OPT_DIAG */
1105 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */