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 */
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 /* 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;
144 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
145 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
147 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
150 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
158 EFSYS_PROBE1(fail1, efx_rc_t, rc);
164 __checkReturn efx_rc_t
165 efx_nvram_get_version(
167 __in efx_nvram_type_t type,
168 __out uint32_t *subtypep,
169 __out_ecount(4) uint16_t version[4])
171 const efx_nvram_ops_t *envop = enp->en_envop;
175 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
176 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
177 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
179 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
182 if ((rc = envop->envo_partn_get_version(enp, partn,
183 subtypep, version)) != 0)
191 EFSYS_PROBE1(fail1, efx_rc_t, rc);
196 __checkReturn efx_rc_t
199 __in efx_nvram_type_t type,
200 __out_opt size_t *chunk_sizep)
202 const efx_nvram_ops_t *envop = enp->en_envop;
206 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
207 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
209 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
212 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
214 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
217 enp->en_nvram_partn_locked = partn;
224 EFSYS_PROBE1(fail1, efx_rc_t, rc);
229 __checkReturn efx_rc_t
230 efx_nvram_read_chunk(
232 __in efx_nvram_type_t type,
233 __in unsigned int offset,
234 __out_bcount(size) caddr_t data,
237 const efx_nvram_ops_t *envop = enp->en_envop;
241 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
242 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
244 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
247 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
249 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
257 EFSYS_PROBE1(fail1, efx_rc_t, rc);
263 * Read from the backup (writeable) store of an A/B partition.
264 * For non A/B partitions, there is only a single store, and so this
265 * function has the same behaviour as efx_nvram_read_chunk().
267 __checkReturn efx_rc_t
268 efx_nvram_read_backup(
270 __in efx_nvram_type_t type,
271 __in unsigned int offset,
272 __out_bcount(size) caddr_t data,
275 const efx_nvram_ops_t *envop = enp->en_envop;
279 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
280 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
282 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
285 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
287 if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
296 EFSYS_PROBE1(fail1, efx_rc_t, rc);
301 __checkReturn efx_rc_t
304 __in efx_nvram_type_t type)
306 const efx_nvram_ops_t *envop = enp->en_envop;
307 unsigned int offset = 0;
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_size(enp, partn, &size)) != 0)
323 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
333 EFSYS_PROBE1(fail1, efx_rc_t, rc);
338 __checkReturn efx_rc_t
339 efx_nvram_write_chunk(
341 __in efx_nvram_type_t type,
342 __in unsigned int offset,
343 __in_bcount(size) caddr_t data,
346 const efx_nvram_ops_t *envop = enp->en_envop;
350 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
351 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
353 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
356 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
358 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
366 EFSYS_PROBE1(fail1, efx_rc_t, rc);
371 __checkReturn efx_rc_t
374 __in efx_nvram_type_t type,
375 __out_opt uint32_t *verify_resultp)
377 const efx_nvram_ops_t *envop = enp->en_envop;
379 uint32_t verify_result = 0;
382 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
383 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
385 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
388 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
390 if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0)
393 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
395 if (verify_resultp != NULL)
396 *verify_resultp = verify_result;
402 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
405 EFSYS_PROBE1(fail1, efx_rc_t, rc);
407 /* Always report verification result */
408 if (verify_resultp != NULL)
409 *verify_resultp = verify_result;
414 __checkReturn efx_rc_t
415 efx_nvram_set_version(
417 __in efx_nvram_type_t type,
418 __in_ecount(4) uint16_t version[4])
420 const efx_nvram_ops_t *envop = enp->en_envop;
424 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
425 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
426 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
428 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
432 * The Siena implementation of envo_set_version() will attempt to
433 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition.
434 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
436 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
438 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
446 EFSYS_PROBE1(fail1, efx_rc_t, rc);
451 /* Validate buffer contents (before writing to flash) */
452 __checkReturn efx_rc_t
455 __in efx_nvram_type_t type,
456 __in_bcount(partn_size) caddr_t partn_data,
457 __in size_t partn_size)
459 const efx_nvram_ops_t *envop = enp->en_envop;
463 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
464 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
465 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
467 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
470 if (envop->envo_buffer_validate != NULL) {
471 if ((rc = envop->envo_buffer_validate(partn,
472 partn_data, partn_size)) != 0)
481 EFSYS_PROBE1(fail1, efx_rc_t, rc);
491 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
492 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
493 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
495 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
497 enp->en_envop = NULL;
498 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
501 #endif /* EFSYS_OPT_NVRAM */
503 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
506 * Internal MCDI request handling
509 __checkReturn efx_rc_t
510 efx_mcdi_nvram_partitions(
512 __out_bcount(size) caddr_t data,
514 __out unsigned int *npartnp)
517 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_PARTITIONS_IN_LEN,
518 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX);
522 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
523 req.emr_in_buf = payload;
524 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
525 req.emr_out_buf = payload;
526 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
528 efx_mcdi_execute(enp, &req);
530 if (req.emr_rc != 0) {
535 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
539 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
541 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
546 if (size < npartn * sizeof (uint32_t)) {
554 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
555 (npartn * sizeof (uint32_t)));
564 EFSYS_PROBE1(fail1, efx_rc_t, rc);
569 __checkReturn efx_rc_t
570 efx_mcdi_nvram_metadata(
573 __out uint32_t *subtypep,
574 __out_ecount(4) uint16_t version[4],
575 __out_bcount_opt(size) char *descp,
579 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_METADATA_IN_LEN,
580 MC_CMD_NVRAM_METADATA_OUT_LENMAX);
583 req.emr_cmd = MC_CMD_NVRAM_METADATA;
584 req.emr_in_buf = payload;
585 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
586 req.emr_out_buf = payload;
587 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
589 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
591 efx_mcdi_execute_quiet(enp, &req);
593 if (req.emr_rc != 0) {
598 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
603 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
604 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
605 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
610 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
611 NVRAM_METADATA_OUT_VERSION_VALID)) {
612 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
613 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
614 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
615 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
617 version[0] = version[1] = version[2] = version[3] = 0;
620 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
621 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
622 /* Return optional descrition string */
623 if ((descp != NULL) && (size > 0)) {
627 desclen = (req.emr_out_length_used
628 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
630 EFSYS_ASSERT3U(desclen, <=,
631 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
633 if (size < desclen) {
638 memcpy(descp, MCDI_OUT2(req, char,
639 NVRAM_METADATA_OUT_DESCRIPTION),
642 /* Ensure string is NUL terminated */
643 descp[desclen] = '\0';
654 EFSYS_PROBE1(fail1, efx_rc_t, rc);
659 __checkReturn efx_rc_t
660 efx_mcdi_nvram_info_ex(
663 __out efx_nvram_info_t *enip)
665 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_INFO_IN_LEN,
666 MC_CMD_NVRAM_INFO_V2_OUT_LEN);
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) {
690 enip->eni_partn_size = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
692 enip->eni_address = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
694 enip->eni_erase_size = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
696 enip->eni_write_size =
697 (req.emr_out_length_used <
698 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
699 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
703 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_INFO_OUT_FLAGS,
704 NVRAM_INFO_OUT_PROTECTED))
705 enip->eni_flags |= EFX_NVRAM_FLAG_READ_ONLY;
707 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_INFO_OUT_FLAGS,
708 NVRAM_INFO_OUT_READ_ONLY))
709 enip->eni_flags |= EFX_NVRAM_FLAG_READ_ONLY;
716 EFSYS_PROBE1(fail1, efx_rc_t, rc);
721 __checkReturn efx_rc_t
725 __out_opt size_t *sizep,
726 __out_opt uint32_t *addressp,
727 __out_opt uint32_t *erase_sizep,
728 __out_opt uint32_t *write_sizep)
730 efx_nvram_info_t eni;
733 if ((rc = efx_mcdi_nvram_info_ex(enp, partn, &eni)) != 0)
737 *sizep = eni.eni_partn_size;
740 *addressp = eni.eni_address;
743 *erase_sizep = eni.eni_erase_size;
746 *write_sizep = eni.eni_write_size;
751 EFSYS_PROBE1(fail1, efx_rc_t, rc);
758 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
759 * NVRAM updates. Older firmware will ignore the flags field in the request.
761 __checkReturn efx_rc_t
762 efx_mcdi_nvram_update_start(
766 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
767 MC_CMD_NVRAM_UPDATE_START_OUT_LEN);
771 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
772 req.emr_in_buf = payload;
773 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
774 req.emr_out_buf = payload;
775 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
777 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
779 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
780 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
782 efx_mcdi_execute(enp, &req);
784 if (req.emr_rc != 0) {
792 EFSYS_PROBE1(fail1, efx_rc_t, rc);
797 __checkReturn efx_rc_t
801 __in uint32_t offset,
802 __out_bcount(size) caddr_t data,
807 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_READ_IN_V2_LEN,
808 MC_CMD_NVRAM_READ_OUT_LENMAX);
811 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
816 req.emr_cmd = MC_CMD_NVRAM_READ;
817 req.emr_in_buf = payload;
818 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
819 req.emr_out_buf = payload;
820 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
822 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
823 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
824 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
825 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
827 efx_mcdi_execute(enp, &req);
829 if (req.emr_rc != 0) {
834 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
840 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
848 EFSYS_PROBE1(fail1, efx_rc_t, rc);
853 __checkReturn efx_rc_t
854 efx_mcdi_nvram_erase(
857 __in uint32_t offset,
861 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_ERASE_IN_LEN,
862 MC_CMD_NVRAM_ERASE_OUT_LEN);
865 req.emr_cmd = MC_CMD_NVRAM_ERASE;
866 req.emr_in_buf = payload;
867 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
868 req.emr_out_buf = payload;
869 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
871 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
872 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
873 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
875 efx_mcdi_execute(enp, &req);
877 if (req.emr_rc != 0) {
885 EFSYS_PROBE1(fail1, efx_rc_t, rc);
891 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
892 * Sienna and EF10 based boards. However EF10 based boards support the use
893 * of this command with payloads up to the maximum MCDI V2 payload length.
895 __checkReturn efx_rc_t
896 efx_mcdi_nvram_write(
899 __in uint32_t offset,
900 __in_bcount(size) caddr_t data,
906 size_t max_data_size;
907 size_t payload_len = enp->en_nic_cfg.enc_mcdi_max_payload_length;
909 max_data_size = payload_len - MC_CMD_NVRAM_WRITE_IN_LEN(0);
910 EFSYS_ASSERT3U(payload_len, >, 0);
911 EFSYS_ASSERT3U(max_data_size, <, payload_len);
913 if (size > max_data_size) {
918 EFSYS_KMEM_ALLOC(enp->en_esip, payload_len, payload);
919 if (payload == NULL) {
924 (void) memset(payload, 0, payload_len);
925 req.emr_cmd = MC_CMD_NVRAM_WRITE;
926 req.emr_in_buf = payload;
927 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
928 req.emr_out_buf = payload;
929 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
931 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
932 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
933 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
935 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
938 efx_mcdi_execute(enp, &req);
940 if (req.emr_rc != 0) {
945 EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
951 EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
955 EFSYS_PROBE1(fail1, efx_rc_t, rc);
962 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
963 * NVRAM updates. Older firmware will ignore the flags field in the request.
965 __checkReturn efx_rc_t
966 efx_mcdi_nvram_update_finish(
969 __in boolean_t reboot,
970 __out_opt uint32_t *verify_resultp)
972 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
974 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
975 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN);
976 uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
979 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
980 req.emr_in_buf = payload;
981 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
982 req.emr_out_buf = payload;
983 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
985 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
986 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
988 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
989 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
991 efx_mcdi_execute(enp, &req);
993 if (req.emr_rc != 0) {
998 if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
999 verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
1000 if (encp->enc_nvram_update_verify_result_supported) {
1001 /* Result of update verification is missing */
1007 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
1010 if ((encp->enc_nvram_update_verify_result_supported) &&
1011 (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) {
1012 /* Update verification failed */
1017 if (verify_resultp != NULL)
1018 *verify_resultp = verify_result;
1027 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1029 /* Always report verification result */
1030 if (verify_resultp != NULL)
1031 *verify_resultp = verify_result;
1038 __checkReturn efx_rc_t
1039 efx_mcdi_nvram_test(
1040 __in efx_nic_t *enp,
1041 __in uint32_t partn)
1044 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_TEST_IN_LEN,
1045 MC_CMD_NVRAM_TEST_OUT_LEN);
1049 req.emr_cmd = MC_CMD_NVRAM_TEST;
1050 req.emr_in_buf = payload;
1051 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1052 req.emr_out_buf = payload;
1053 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1055 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1057 efx_mcdi_execute(enp, &req);
1059 if (req.emr_rc != 0) {
1064 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1069 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1070 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1072 EFSYS_PROBE1(nvram_test_failure, int, partn);
1085 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1090 #endif /* EFSYS_OPT_DIAG */
1093 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */