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_erase, /* envo_partn_erase */
52 siena_nvram_partn_write, /* envo_partn_write */
53 siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */
54 siena_nvram_partn_get_version, /* envo_partn_get_version */
55 siena_nvram_partn_set_version, /* envo_partn_set_version */
56 NULL, /* envo_partn_validate */
59 #endif /* EFSYS_OPT_SIENA */
61 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
63 static const efx_nvram_ops_t __efx_nvram_ef10_ops = {
65 ef10_nvram_test, /* envo_test */
66 #endif /* EFSYS_OPT_DIAG */
67 ef10_nvram_type_to_partn, /* envo_type_to_partn */
68 ef10_nvram_partn_size, /* envo_partn_size */
69 ef10_nvram_partn_rw_start, /* envo_partn_rw_start */
70 ef10_nvram_partn_read, /* envo_partn_read */
71 ef10_nvram_partn_erase, /* envo_partn_erase */
72 ef10_nvram_partn_write, /* envo_partn_write */
73 ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */
74 ef10_nvram_partn_get_version, /* envo_partn_get_version */
75 ef10_nvram_partn_set_version, /* envo_partn_set_version */
76 ef10_nvram_buffer_validate, /* envo_buffer_validate */
79 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
81 __checkReturn efx_rc_t
85 const efx_nvram_ops_t *envop;
88 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
89 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
90 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
92 switch (enp->en_family) {
94 case EFX_FAMILY_SIENA:
95 envop = &__efx_nvram_siena_ops;
97 #endif /* EFSYS_OPT_SIENA */
99 #if EFSYS_OPT_HUNTINGTON
100 case EFX_FAMILY_HUNTINGTON:
101 envop = &__efx_nvram_ef10_ops;
103 #endif /* EFSYS_OPT_HUNTINGTON */
105 #if EFSYS_OPT_MEDFORD
106 case EFX_FAMILY_MEDFORD:
107 envop = &__efx_nvram_ef10_ops;
109 #endif /* EFSYS_OPT_MEDFORD */
117 enp->en_envop = envop;
118 enp->en_mod_flags |= EFX_MOD_NVRAM;
123 EFSYS_PROBE1(fail1, efx_rc_t, rc);
130 __checkReturn efx_rc_t
134 const efx_nvram_ops_t *envop = enp->en_envop;
137 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
138 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
140 if ((rc = envop->envo_test(enp)) != 0)
146 EFSYS_PROBE1(fail1, efx_rc_t, rc);
151 #endif /* EFSYS_OPT_DIAG */
153 __checkReturn efx_rc_t
156 __in efx_nvram_type_t type,
159 const efx_nvram_ops_t *envop = enp->en_envop;
163 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
164 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
166 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
168 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
171 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
179 EFSYS_PROBE1(fail1, efx_rc_t, rc);
185 __checkReturn efx_rc_t
186 efx_nvram_get_version(
188 __in efx_nvram_type_t type,
189 __out uint32_t *subtypep,
190 __out_ecount(4) uint16_t version[4])
192 const efx_nvram_ops_t *envop = enp->en_envop;
196 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
197 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
198 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
200 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
202 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
205 if ((rc = envop->envo_partn_get_version(enp, partn,
206 subtypep, version)) != 0)
214 EFSYS_PROBE1(fail1, efx_rc_t, rc);
219 __checkReturn efx_rc_t
222 __in efx_nvram_type_t type,
223 __out_opt size_t *chunk_sizep)
225 const efx_nvram_ops_t *envop = enp->en_envop;
229 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
230 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
232 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
233 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
235 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
237 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
240 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
243 enp->en_nvram_locked = type;
250 EFSYS_PROBE1(fail1, efx_rc_t, rc);
255 __checkReturn efx_rc_t
256 efx_nvram_read_chunk(
258 __in efx_nvram_type_t type,
259 __in unsigned int offset,
260 __out_bcount(size) caddr_t data,
263 const efx_nvram_ops_t *envop = enp->en_envop;
267 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
268 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
270 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
271 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
273 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
275 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
278 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
286 EFSYS_PROBE1(fail1, efx_rc_t, rc);
291 __checkReturn efx_rc_t
294 __in efx_nvram_type_t type)
296 const efx_nvram_ops_t *envop = enp->en_envop;
297 unsigned int offset = 0;
302 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
303 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
305 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
306 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
308 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
310 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
313 if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
316 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
326 EFSYS_PROBE1(fail1, efx_rc_t, rc);
331 __checkReturn efx_rc_t
332 efx_nvram_write_chunk(
334 __in efx_nvram_type_t type,
335 __in unsigned int offset,
336 __in_bcount(size) caddr_t data,
339 const efx_nvram_ops_t *envop = enp->en_envop;
343 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
344 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
346 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
347 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
349 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
351 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
354 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
362 EFSYS_PROBE1(fail1, efx_rc_t, rc);
367 __checkReturn efx_rc_t
370 __in efx_nvram_type_t type)
372 const efx_nvram_ops_t *envop = enp->en_envop;
376 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
377 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
379 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
380 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
382 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
384 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
387 if ((rc = envop->envo_partn_rw_finish(enp, partn)) != 0)
390 enp->en_nvram_locked = EFX_NVRAM_INVALID;
396 enp->en_nvram_locked = EFX_NVRAM_INVALID;
399 EFSYS_PROBE1(fail1, efx_rc_t, rc);
404 __checkReturn efx_rc_t
405 efx_nvram_set_version(
407 __in efx_nvram_type_t type,
408 __in_ecount(4) uint16_t version[4])
410 const efx_nvram_ops_t *envop = enp->en_envop;
414 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
415 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
416 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
418 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
421 * The Siena implementation of envo_set_version() will attempt to
422 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
423 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
425 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
427 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
430 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
438 EFSYS_PROBE1(fail1, efx_rc_t, rc);
443 /* Validate buffer contents (before writing to flash) */
444 __checkReturn efx_rc_t
447 __in efx_nvram_type_t type,
448 __in_bcount(partn_size) caddr_t partn_data,
449 __in size_t partn_size)
451 const efx_nvram_ops_t *envop = enp->en_envop;
455 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
456 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
457 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
459 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
462 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
465 if (envop->envo_buffer_validate != NULL) {
466 if ((rc = envop->envo_buffer_validate(enp, partn,
467 partn_data, partn_size)) != 0)
476 EFSYS_PROBE1(fail1, efx_rc_t, rc);
486 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
487 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
488 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
490 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
492 enp->en_envop = NULL;
493 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
496 #endif /* EFSYS_OPT_NVRAM */
498 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
501 * Internal MCDI request handling
504 __checkReturn efx_rc_t
505 efx_mcdi_nvram_partitions(
507 __out_bcount(size) caddr_t data,
509 __out unsigned int *npartnp)
512 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
513 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
517 (void) memset(payload, 0, sizeof (payload));
518 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
519 req.emr_in_buf = payload;
520 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
521 req.emr_out_buf = payload;
522 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
524 efx_mcdi_execute(enp, &req);
526 if (req.emr_rc != 0) {
531 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
535 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
537 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
542 if (size < npartn * sizeof (uint32_t)) {
550 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
551 (npartn * sizeof (uint32_t)));
560 EFSYS_PROBE1(fail1, efx_rc_t, rc);
565 __checkReturn efx_rc_t
566 efx_mcdi_nvram_metadata(
569 __out uint32_t *subtypep,
570 __out_ecount(4) uint16_t version[4],
571 __out_bcount_opt(size) char *descp,
575 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
576 MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
579 (void) memset(payload, 0, sizeof (payload));
580 req.emr_cmd = MC_CMD_NVRAM_METADATA;
581 req.emr_in_buf = payload;
582 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
583 req.emr_out_buf = payload;
584 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
586 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
588 efx_mcdi_execute(enp, &req);
590 if (req.emr_rc != 0) {
595 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
600 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
601 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
602 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
607 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
608 NVRAM_METADATA_OUT_VERSION_VALID)) {
609 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
610 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
611 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
612 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
614 version[0] = version[1] = version[2] = version[3] = 0;
617 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
618 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
619 /* Return optional descrition string */
620 if ((descp != NULL) && (size > 0)) {
624 desclen = (req.emr_out_length_used
625 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
627 EFSYS_ASSERT3U(desclen, <=,
628 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
630 if (size < desclen) {
635 memcpy(descp, MCDI_OUT2(req, char,
636 NVRAM_METADATA_OUT_DESCRIPTION),
639 /* Ensure string is NUL terminated */
640 descp[desclen] = '\0';
651 EFSYS_PROBE1(fail1, efx_rc_t, rc);
656 __checkReturn efx_rc_t
660 __out_opt size_t *sizep,
661 __out_opt uint32_t *addressp,
662 __out_opt uint32_t *erase_sizep,
663 __out_opt uint32_t *write_sizep)
665 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
666 MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
670 (void) memset(payload, 0, sizeof (payload));
671 req.emr_cmd = MC_CMD_NVRAM_INFO;
672 req.emr_in_buf = payload;
673 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
674 req.emr_out_buf = payload;
675 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
677 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
679 efx_mcdi_execute_quiet(enp, &req);
681 if (req.emr_rc != 0) {
686 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
692 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
695 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
698 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
702 (req.emr_out_length_used <
703 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
704 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
712 EFSYS_PROBE1(fail1, efx_rc_t, rc);
718 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
719 * NVRAM updates. Older firmware will ignore the flags field in the request.
721 __checkReturn efx_rc_t
722 efx_mcdi_nvram_update_start(
726 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
727 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
731 (void) memset(payload, 0, sizeof (payload));
732 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
733 req.emr_in_buf = payload;
734 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
735 req.emr_out_buf = payload;
736 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
738 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
740 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
741 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
743 efx_mcdi_execute(enp, &req);
745 if (req.emr_rc != 0) {
753 EFSYS_PROBE1(fail1, efx_rc_t, rc);
758 __checkReturn efx_rc_t
762 __in uint32_t offset,
763 __out_bcount(size) caddr_t data,
768 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
769 MC_CMD_NVRAM_READ_OUT_LENMAX)];
772 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
777 (void) memset(payload, 0, sizeof (payload));
778 req.emr_cmd = MC_CMD_NVRAM_READ;
779 req.emr_in_buf = payload;
780 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
781 req.emr_out_buf = payload;
782 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
784 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
785 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
786 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
787 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
789 efx_mcdi_execute(enp, &req);
791 if (req.emr_rc != 0) {
796 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
802 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
810 EFSYS_PROBE1(fail1, efx_rc_t, rc);
815 __checkReturn efx_rc_t
816 efx_mcdi_nvram_erase(
819 __in uint32_t offset,
823 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
824 MC_CMD_NVRAM_ERASE_OUT_LEN)];
827 (void) memset(payload, 0, sizeof (payload));
828 req.emr_cmd = MC_CMD_NVRAM_ERASE;
829 req.emr_in_buf = payload;
830 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
831 req.emr_out_buf = payload;
832 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
834 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
835 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
836 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
838 efx_mcdi_execute(enp, &req);
840 if (req.emr_rc != 0) {
848 EFSYS_PROBE1(fail1, efx_rc_t, rc);
854 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
855 * Sienna and EF10 based boards. However EF10 based boards support the use
856 * of this command with payloads up to the maximum MCDI V2 payload length.
858 __checkReturn efx_rc_t
859 efx_mcdi_nvram_write(
862 __in uint32_t offset,
863 __in_bcount(size) caddr_t data,
869 size_t max_data_size;
870 size_t payload_len = enp->en_nic_cfg.enc_mcdi_max_payload_length;
872 max_data_size = payload_len - MC_CMD_NVRAM_WRITE_IN_LEN(0);
873 EFSYS_ASSERT3U(payload_len, >, 0);
874 EFSYS_ASSERT3U(max_data_size, <, payload_len);
876 if (size > max_data_size) {
881 EFSYS_KMEM_ALLOC(enp->en_esip, payload_len, payload);
882 if (payload == NULL) {
887 (void) memset(payload, 0, payload_len);
888 req.emr_cmd = MC_CMD_NVRAM_WRITE;
889 req.emr_in_buf = payload;
890 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
891 req.emr_out_buf = payload;
892 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
894 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
895 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
896 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
898 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
901 efx_mcdi_execute(enp, &req);
903 if (req.emr_rc != 0) {
908 EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
914 EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
918 EFSYS_PROBE1(fail1, efx_rc_t, rc);
925 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
926 * NVRAM updates. Older firmware will ignore the flags field in the request.
928 __checkReturn efx_rc_t
929 efx_mcdi_nvram_update_finish(
932 __in boolean_t reboot,
933 __out_opt uint32_t *resultp)
935 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
937 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
938 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)];
939 uint32_t result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
942 (void) memset(payload, 0, sizeof (payload));
943 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
944 req.emr_in_buf = payload;
945 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
946 req.emr_out_buf = payload;
947 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
949 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
950 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
952 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
953 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
955 efx_mcdi_execute(enp, &req);
957 if (req.emr_rc != 0) {
962 if (encp->enc_fw_verified_nvram_update_required == B_FALSE) {
963 /* Report success if verified updates are not supported. */
964 result = MC_CMD_NVRAM_VERIFY_RC_SUCCESS;
966 /* Firmware-verified NVRAM updates are required */
967 if (req.emr_out_length_used <
968 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
973 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
975 if (result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) {
976 /* Mandatory verification failed */
992 EFSYS_PROBE1(fail1, efx_rc_t, rc);
994 /* Always report verification result */
1003 __checkReturn efx_rc_t
1004 efx_mcdi_nvram_test(
1005 __in efx_nic_t *enp,
1006 __in uint32_t partn)
1009 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
1010 MC_CMD_NVRAM_TEST_OUT_LEN)];
1014 (void) memset(payload, 0, sizeof (payload));
1015 req.emr_cmd = MC_CMD_NVRAM_TEST;
1016 req.emr_in_buf = payload;
1017 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1018 req.emr_out_buf = payload;
1019 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1021 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1023 efx_mcdi_execute(enp, &req);
1025 if (req.emr_rc != 0) {
1030 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1035 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1036 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1038 EFSYS_PROBE1(nvram_test_failure, int, partn);
1051 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1056 #endif /* EFSYS_OPT_DIAG */
1059 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */