2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2009-2016 Solarflare Communications Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * The views and conclusions contained in the software and documentation are
29 * those of the authors and should not be interpreted as representing official
30 * policies, either expressed or implied, of the FreeBSD Project.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
43 static const efx_nvram_ops_t __efx_nvram_siena_ops = {
45 siena_nvram_test, /* envo_test */
46 #endif /* EFSYS_OPT_DIAG */
47 siena_nvram_type_to_partn, /* envo_type_to_partn */
48 siena_nvram_partn_size, /* envo_partn_size */
49 siena_nvram_partn_rw_start, /* envo_partn_rw_start */
50 siena_nvram_partn_read, /* envo_partn_read */
51 siena_nvram_partn_read, /* envo_partn_read_backup */
52 siena_nvram_partn_erase, /* envo_partn_erase */
53 siena_nvram_partn_write, /* envo_partn_write */
54 siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */
55 siena_nvram_partn_get_version, /* envo_partn_get_version */
56 siena_nvram_partn_set_version, /* envo_partn_set_version */
57 NULL, /* envo_partn_validate */
60 #endif /* EFSYS_OPT_SIENA */
62 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
64 static const efx_nvram_ops_t __efx_nvram_ef10_ops = {
66 ef10_nvram_test, /* envo_test */
67 #endif /* EFSYS_OPT_DIAG */
68 ef10_nvram_type_to_partn, /* envo_type_to_partn */
69 ef10_nvram_partn_size, /* envo_partn_size */
70 ef10_nvram_partn_rw_start, /* envo_partn_rw_start */
71 ef10_nvram_partn_read, /* envo_partn_read */
72 ef10_nvram_partn_read_backup, /* envo_partn_read_backup */
73 ef10_nvram_partn_erase, /* envo_partn_erase */
74 ef10_nvram_partn_write, /* envo_partn_write */
75 ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */
76 ef10_nvram_partn_get_version, /* envo_partn_get_version */
77 ef10_nvram_partn_set_version, /* envo_partn_set_version */
78 ef10_nvram_buffer_validate, /* envo_buffer_validate */
81 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
83 __checkReturn efx_rc_t
87 const efx_nvram_ops_t *envop;
90 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
91 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
92 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
94 switch (enp->en_family) {
96 case EFX_FAMILY_SIENA:
97 envop = &__efx_nvram_siena_ops;
99 #endif /* EFSYS_OPT_SIENA */
101 #if EFSYS_OPT_HUNTINGTON
102 case EFX_FAMILY_HUNTINGTON:
103 envop = &__efx_nvram_ef10_ops;
105 #endif /* EFSYS_OPT_HUNTINGTON */
107 #if EFSYS_OPT_MEDFORD
108 case EFX_FAMILY_MEDFORD:
109 envop = &__efx_nvram_ef10_ops;
111 #endif /* EFSYS_OPT_MEDFORD */
113 #if EFSYS_OPT_MEDFORD2
114 case EFX_FAMILY_MEDFORD2:
115 envop = &__efx_nvram_ef10_ops;
117 #endif /* EFSYS_OPT_MEDFORD2 */
125 enp->en_envop = envop;
126 enp->en_mod_flags |= EFX_MOD_NVRAM;
128 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
133 EFSYS_PROBE1(fail1, efx_rc_t, rc);
140 __checkReturn efx_rc_t
144 const efx_nvram_ops_t *envop = enp->en_envop;
147 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
148 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
150 if ((rc = envop->envo_test(enp)) != 0)
156 EFSYS_PROBE1(fail1, efx_rc_t, rc);
161 #endif /* EFSYS_OPT_DIAG */
163 __checkReturn efx_rc_t
166 __in efx_nvram_type_t type,
169 const efx_nvram_ops_t *envop = enp->en_envop;
173 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
174 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
176 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
179 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
187 EFSYS_PROBE1(fail1, efx_rc_t, rc);
193 __checkReturn efx_rc_t
194 efx_nvram_get_version(
196 __in efx_nvram_type_t type,
197 __out uint32_t *subtypep,
198 __out_ecount(4) uint16_t version[4])
200 const efx_nvram_ops_t *envop = enp->en_envop;
204 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
205 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
206 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
208 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
211 if ((rc = envop->envo_partn_get_version(enp, partn,
212 subtypep, version)) != 0)
220 EFSYS_PROBE1(fail1, efx_rc_t, rc);
225 __checkReturn efx_rc_t
228 __in efx_nvram_type_t type,
229 __out_opt size_t *chunk_sizep)
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, ==, EFX_NVRAM_PARTN_INVALID);
243 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
246 enp->en_nvram_partn_locked = partn;
253 EFSYS_PROBE1(fail1, efx_rc_t, rc);
258 __checkReturn efx_rc_t
259 efx_nvram_read_chunk(
261 __in efx_nvram_type_t type,
262 __in unsigned int offset,
263 __out_bcount(size) caddr_t data,
266 const efx_nvram_ops_t *envop = enp->en_envop;
270 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
271 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
273 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
276 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
278 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
286 EFSYS_PROBE1(fail1, efx_rc_t, rc);
292 * Read from the backup (writeable) store of an A/B partition.
293 * For non A/B partitions, there is only a single store, and so this
294 * function has the same behaviour as efx_nvram_read_chunk().
296 __checkReturn efx_rc_t
297 efx_nvram_read_backup(
299 __in efx_nvram_type_t type,
300 __in unsigned int offset,
301 __out_bcount(size) caddr_t data,
304 const efx_nvram_ops_t *envop = enp->en_envop;
308 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
309 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
311 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
314 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
316 if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
325 EFSYS_PROBE1(fail1, efx_rc_t, rc);
330 __checkReturn efx_rc_t
333 __in efx_nvram_type_t type)
335 const efx_nvram_ops_t *envop = enp->en_envop;
336 unsigned int offset = 0;
341 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
342 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
344 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
347 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
349 if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
352 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
362 EFSYS_PROBE1(fail1, efx_rc_t, rc);
367 __checkReturn efx_rc_t
368 efx_nvram_write_chunk(
370 __in efx_nvram_type_t type,
371 __in unsigned int offset,
372 __in_bcount(size) caddr_t data,
375 const efx_nvram_ops_t *envop = enp->en_envop;
379 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
380 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
382 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
385 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
387 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
395 EFSYS_PROBE1(fail1, efx_rc_t, rc);
400 __checkReturn efx_rc_t
403 __in efx_nvram_type_t type,
404 __out_opt uint32_t *verify_resultp)
406 const efx_nvram_ops_t *envop = enp->en_envop;
408 uint32_t verify_result = 0;
411 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
412 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
414 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
417 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
419 if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0)
422 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
424 if (verify_resultp != NULL)
425 *verify_resultp = verify_result;
431 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
434 EFSYS_PROBE1(fail1, efx_rc_t, rc);
436 /* Always report verification result */
437 if (verify_resultp != NULL)
438 *verify_resultp = verify_result;
443 __checkReturn efx_rc_t
444 efx_nvram_set_version(
446 __in efx_nvram_type_t type,
447 __in_ecount(4) uint16_t version[4])
449 const efx_nvram_ops_t *envop = enp->en_envop;
453 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
454 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
455 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
457 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
461 * The Siena implementation of envo_set_version() will attempt to
462 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition.
463 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
465 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
467 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
475 EFSYS_PROBE1(fail1, efx_rc_t, rc);
480 /* Validate buffer contents (before writing to flash) */
481 __checkReturn efx_rc_t
484 __in efx_nvram_type_t type,
485 __in_bcount(partn_size) caddr_t partn_data,
486 __in size_t partn_size)
488 const efx_nvram_ops_t *envop = enp->en_envop;
492 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
493 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
494 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
496 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
499 if (envop->envo_buffer_validate != NULL) {
500 if ((rc = envop->envo_buffer_validate(enp, partn,
501 partn_data, partn_size)) != 0)
510 EFSYS_PROBE1(fail1, efx_rc_t, rc);
520 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
521 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
522 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
524 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
526 enp->en_envop = NULL;
527 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
530 #endif /* EFSYS_OPT_NVRAM */
532 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
535 * Internal MCDI request handling
538 __checkReturn efx_rc_t
539 efx_mcdi_nvram_partitions(
541 __out_bcount(size) caddr_t data,
543 __out unsigned int *npartnp)
546 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
547 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
551 (void) memset(payload, 0, sizeof (payload));
552 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
553 req.emr_in_buf = payload;
554 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
555 req.emr_out_buf = payload;
556 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
558 efx_mcdi_execute(enp, &req);
560 if (req.emr_rc != 0) {
565 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
569 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
571 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
576 if (size < npartn * sizeof (uint32_t)) {
584 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
585 (npartn * sizeof (uint32_t)));
594 EFSYS_PROBE1(fail1, efx_rc_t, rc);
599 __checkReturn efx_rc_t
600 efx_mcdi_nvram_metadata(
603 __out uint32_t *subtypep,
604 __out_ecount(4) uint16_t version[4],
605 __out_bcount_opt(size) char *descp,
609 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
610 MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
613 (void) memset(payload, 0, sizeof (payload));
614 req.emr_cmd = MC_CMD_NVRAM_METADATA;
615 req.emr_in_buf = payload;
616 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
617 req.emr_out_buf = payload;
618 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
620 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
622 efx_mcdi_execute_quiet(enp, &req);
624 if (req.emr_rc != 0) {
629 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
634 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
635 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
636 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
641 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
642 NVRAM_METADATA_OUT_VERSION_VALID)) {
643 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
644 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
645 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
646 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
648 version[0] = version[1] = version[2] = version[3] = 0;
651 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
652 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
653 /* Return optional descrition string */
654 if ((descp != NULL) && (size > 0)) {
658 desclen = (req.emr_out_length_used
659 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
661 EFSYS_ASSERT3U(desclen, <=,
662 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
664 if (size < desclen) {
669 memcpy(descp, MCDI_OUT2(req, char,
670 NVRAM_METADATA_OUT_DESCRIPTION),
673 /* Ensure string is NUL terminated */
674 descp[desclen] = '\0';
685 EFSYS_PROBE1(fail1, efx_rc_t, rc);
690 __checkReturn efx_rc_t
694 __out_opt size_t *sizep,
695 __out_opt uint32_t *addressp,
696 __out_opt uint32_t *erase_sizep,
697 __out_opt uint32_t *write_sizep)
699 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
700 MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
704 (void) memset(payload, 0, sizeof (payload));
705 req.emr_cmd = MC_CMD_NVRAM_INFO;
706 req.emr_in_buf = payload;
707 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
708 req.emr_out_buf = payload;
709 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
711 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
713 efx_mcdi_execute_quiet(enp, &req);
715 if (req.emr_rc != 0) {
720 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
726 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
729 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
732 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
736 (req.emr_out_length_used <
737 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
738 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
746 EFSYS_PROBE1(fail1, efx_rc_t, rc);
752 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
753 * NVRAM updates. Older firmware will ignore the flags field in the request.
755 __checkReturn efx_rc_t
756 efx_mcdi_nvram_update_start(
760 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
761 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
765 (void) memset(payload, 0, sizeof (payload));
766 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
767 req.emr_in_buf = payload;
768 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
769 req.emr_out_buf = payload;
770 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
772 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
774 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
775 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
777 efx_mcdi_execute(enp, &req);
779 if (req.emr_rc != 0) {
787 EFSYS_PROBE1(fail1, efx_rc_t, rc);
792 __checkReturn efx_rc_t
796 __in uint32_t offset,
797 __out_bcount(size) caddr_t data,
802 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
803 MC_CMD_NVRAM_READ_OUT_LENMAX)];
806 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
811 (void) memset(payload, 0, sizeof (payload));
812 req.emr_cmd = MC_CMD_NVRAM_READ;
813 req.emr_in_buf = payload;
814 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
815 req.emr_out_buf = payload;
816 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
818 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
819 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
820 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
821 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
823 efx_mcdi_execute(enp, &req);
825 if (req.emr_rc != 0) {
830 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
836 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
844 EFSYS_PROBE1(fail1, efx_rc_t, rc);
849 __checkReturn efx_rc_t
850 efx_mcdi_nvram_erase(
853 __in uint32_t offset,
857 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
858 MC_CMD_NVRAM_ERASE_OUT_LEN)];
861 (void) memset(payload, 0, sizeof (payload));
862 req.emr_cmd = MC_CMD_NVRAM_ERASE;
863 req.emr_in_buf = payload;
864 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
865 req.emr_out_buf = payload;
866 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
868 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
869 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
870 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
872 efx_mcdi_execute(enp, &req);
874 if (req.emr_rc != 0) {
882 EFSYS_PROBE1(fail1, efx_rc_t, rc);
888 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
889 * Sienna and EF10 based boards. However EF10 based boards support the use
890 * of this command with payloads up to the maximum MCDI V2 payload length.
892 __checkReturn efx_rc_t
893 efx_mcdi_nvram_write(
896 __in uint32_t offset,
897 __in_bcount(size) caddr_t data,
901 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1,
902 MCDI_CTL_SDU_LEN_MAX_V2)];
904 size_t max_data_size;
906 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length
907 - MC_CMD_NVRAM_WRITE_IN_LEN(0);
908 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0);
909 EFSYS_ASSERT3U(max_data_size, <,
910 enp->en_nic_cfg.enc_mcdi_max_payload_length);
912 if (size > max_data_size) {
917 (void) memset(payload, 0, sizeof (payload));
918 req.emr_cmd = MC_CMD_NVRAM_WRITE;
919 req.emr_in_buf = payload;
920 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
921 req.emr_out_buf = payload;
922 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
924 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
925 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
926 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
928 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
931 efx_mcdi_execute(enp, &req);
933 if (req.emr_rc != 0) {
943 EFSYS_PROBE1(fail1, efx_rc_t, rc);
950 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
951 * NVRAM updates. Older firmware will ignore the flags field in the request.
953 __checkReturn efx_rc_t
954 efx_mcdi_nvram_update_finish(
957 __in boolean_t reboot,
958 __out_opt uint32_t *verify_resultp)
960 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
962 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
963 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)];
964 uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
967 (void) memset(payload, 0, sizeof (payload));
968 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
969 req.emr_in_buf = payload;
970 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
971 req.emr_out_buf = payload;
972 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
974 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
975 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
977 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
978 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
980 efx_mcdi_execute(enp, &req);
982 if (req.emr_rc != 0) {
987 if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
988 verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
989 if (encp->enc_nvram_update_verify_result_supported) {
990 /* Result of update verification is missing */
996 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
999 if ((encp->enc_nvram_update_verify_result_supported) &&
1000 (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) {
1001 /* Update verification failed */
1006 if (verify_resultp != NULL)
1007 *verify_resultp = verify_result;
1016 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1018 /* Always report verification result */
1019 if (verify_resultp != NULL)
1020 *verify_resultp = verify_result;
1027 __checkReturn efx_rc_t
1028 efx_mcdi_nvram_test(
1029 __in efx_nic_t *enp,
1030 __in uint32_t partn)
1033 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
1034 MC_CMD_NVRAM_TEST_OUT_LEN)];
1038 (void) memset(payload, 0, sizeof (payload));
1039 req.emr_cmd = MC_CMD_NVRAM_TEST;
1040 req.emr_in_buf = payload;
1041 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1042 req.emr_out_buf = payload;
1043 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1045 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1047 efx_mcdi_execute(enp, &req);
1049 if (req.emr_rc != 0) {
1054 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1059 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1060 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1062 EFSYS_PROBE1(nvram_test_failure, int, partn);
1075 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1080 #endif /* EFSYS_OPT_DIAG */
1083 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */