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_type_to_partn != NULL &&
466 ((rc = envop->envo_buffer_validate(enp, partn,
467 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_locked, ==, EFX_NVRAM_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(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 *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 result = 0; /* FIXME: use 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 (encp->enc_fw_verified_nvram_update_required == B_FALSE) {
953 /* Report success if verified updates are not supported. */
954 result = MC_CMD_NVRAM_VERIFY_RC_SUCCESS;
956 /* Firmware-verified NVRAM updates are required */
957 if (req.emr_out_length_used <
958 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
963 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
965 if (result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) {
966 /* Mandatory verification failed */
982 EFSYS_PROBE1(fail1, efx_rc_t, rc);
984 /* Always report verification result */
993 __checkReturn efx_rc_t
999 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
1000 MC_CMD_NVRAM_TEST_OUT_LEN)];
1004 (void) memset(payload, 0, sizeof (payload));
1005 req.emr_cmd = MC_CMD_NVRAM_TEST;
1006 req.emr_in_buf = payload;
1007 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1008 req.emr_out_buf = payload;
1009 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1011 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1013 efx_mcdi_execute(enp, &req);
1015 if (req.emr_rc != 0) {
1020 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1025 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1026 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1028 EFSYS_PROBE1(nvram_test_failure, int, partn);
1041 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1046 #endif /* EFSYS_OPT_DIAG */
1049 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */