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
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 */
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 */
119 enp->en_envop = envop;
120 enp->en_mod_flags |= EFX_MOD_NVRAM;
122 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
127 EFSYS_PROBE1(fail1, efx_rc_t, rc);
134 __checkReturn efx_rc_t
138 const efx_nvram_ops_t *envop = enp->en_envop;
141 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
142 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
144 if ((rc = envop->envo_test(enp)) != 0)
150 EFSYS_PROBE1(fail1, efx_rc_t, rc);
155 #endif /* EFSYS_OPT_DIAG */
157 __checkReturn efx_rc_t
160 __in efx_nvram_type_t type,
163 const efx_nvram_ops_t *envop = enp->en_envop;
167 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
168 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
170 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
173 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
181 EFSYS_PROBE1(fail1, efx_rc_t, rc);
187 __checkReturn efx_rc_t
188 efx_nvram_get_version(
190 __in efx_nvram_type_t type,
191 __out uint32_t *subtypep,
192 __out_ecount(4) uint16_t version[4])
194 const efx_nvram_ops_t *envop = enp->en_envop;
198 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
199 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
200 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
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 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
235 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
237 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
240 enp->en_nvram_partn_locked = partn;
247 EFSYS_PROBE1(fail1, efx_rc_t, rc);
252 __checkReturn efx_rc_t
253 efx_nvram_read_chunk(
255 __in efx_nvram_type_t type,
256 __in unsigned int offset,
257 __out_bcount(size) caddr_t data,
260 const efx_nvram_ops_t *envop = enp->en_envop;
264 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
265 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
267 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
270 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
272 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
280 EFSYS_PROBE1(fail1, efx_rc_t, rc);
286 * Read from the backup (writeable) store of an A/B partition.
287 * For non A/B partitions, there is only a single store, and so this
288 * function has the same behaviour as efx_nvram_read_chunk().
290 __checkReturn efx_rc_t
291 efx_nvram_read_backup(
293 __in efx_nvram_type_t type,
294 __in unsigned int offset,
295 __out_bcount(size) caddr_t data,
298 const efx_nvram_ops_t *envop = enp->en_envop;
302 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
303 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
305 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
308 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
310 if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
319 EFSYS_PROBE1(fail1, efx_rc_t, rc);
324 __checkReturn efx_rc_t
327 __in efx_nvram_type_t type)
329 const efx_nvram_ops_t *envop = enp->en_envop;
330 unsigned int offset = 0;
335 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
336 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
338 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
341 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
343 if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
346 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
356 EFSYS_PROBE1(fail1, efx_rc_t, rc);
361 __checkReturn efx_rc_t
362 efx_nvram_write_chunk(
364 __in efx_nvram_type_t type,
365 __in unsigned int offset,
366 __in_bcount(size) caddr_t data,
369 const efx_nvram_ops_t *envop = enp->en_envop;
373 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
374 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
376 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
379 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
381 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
389 EFSYS_PROBE1(fail1, efx_rc_t, rc);
394 __checkReturn efx_rc_t
397 __in efx_nvram_type_t type,
398 __out_opt uint32_t *verify_resultp)
400 const efx_nvram_ops_t *envop = enp->en_envop;
402 uint32_t verify_result = 0;
405 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
406 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
408 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
411 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
413 if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0)
416 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
418 if (verify_resultp != NULL)
419 *verify_resultp = verify_result;
425 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
428 EFSYS_PROBE1(fail1, efx_rc_t, rc);
430 /* Always report verification result */
431 if (verify_resultp != NULL)
432 *verify_resultp = verify_result;
437 __checkReturn efx_rc_t
438 efx_nvram_set_version(
440 __in efx_nvram_type_t type,
441 __in_ecount(4) uint16_t version[4])
443 const efx_nvram_ops_t *envop = enp->en_envop;
447 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
448 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
449 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
451 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
455 * The Siena implementation of envo_set_version() will attempt to
456 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition.
457 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
459 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
461 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
469 EFSYS_PROBE1(fail1, efx_rc_t, rc);
474 /* Validate buffer contents (before writing to flash) */
475 __checkReturn efx_rc_t
478 __in efx_nvram_type_t type,
479 __in_bcount(partn_size) caddr_t partn_data,
480 __in size_t partn_size)
482 const efx_nvram_ops_t *envop = enp->en_envop;
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 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
493 if (envop->envo_buffer_validate != NULL) {
494 if ((rc = envop->envo_buffer_validate(enp, partn,
495 partn_data, partn_size)) != 0)
504 EFSYS_PROBE1(fail1, efx_rc_t, rc);
514 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
515 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
516 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
518 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
520 enp->en_envop = NULL;
521 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
524 #endif /* EFSYS_OPT_NVRAM */
526 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
529 * Internal MCDI request handling
532 __checkReturn efx_rc_t
533 efx_mcdi_nvram_partitions(
535 __out_bcount(size) caddr_t data,
537 __out unsigned int *npartnp)
540 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
541 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
545 (void) memset(payload, 0, sizeof (payload));
546 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
547 req.emr_in_buf = payload;
548 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
549 req.emr_out_buf = payload;
550 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
552 efx_mcdi_execute(enp, &req);
554 if (req.emr_rc != 0) {
559 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
563 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
565 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
570 if (size < npartn * sizeof (uint32_t)) {
578 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
579 (npartn * sizeof (uint32_t)));
588 EFSYS_PROBE1(fail1, efx_rc_t, rc);
593 __checkReturn efx_rc_t
594 efx_mcdi_nvram_metadata(
597 __out uint32_t *subtypep,
598 __out_ecount(4) uint16_t version[4],
599 __out_bcount_opt(size) char *descp,
603 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
604 MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
607 (void) memset(payload, 0, sizeof (payload));
608 req.emr_cmd = MC_CMD_NVRAM_METADATA;
609 req.emr_in_buf = payload;
610 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
611 req.emr_out_buf = payload;
612 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
614 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
616 efx_mcdi_execute(enp, &req);
618 if (req.emr_rc != 0) {
623 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
628 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
629 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
630 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
635 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
636 NVRAM_METADATA_OUT_VERSION_VALID)) {
637 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
638 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
639 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
640 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
642 version[0] = version[1] = version[2] = version[3] = 0;
645 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
646 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
647 /* Return optional descrition string */
648 if ((descp != NULL) && (size > 0)) {
652 desclen = (req.emr_out_length_used
653 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
655 EFSYS_ASSERT3U(desclen, <=,
656 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
658 if (size < desclen) {
663 memcpy(descp, MCDI_OUT2(req, char,
664 NVRAM_METADATA_OUT_DESCRIPTION),
667 /* Ensure string is NUL terminated */
668 descp[desclen] = '\0';
679 EFSYS_PROBE1(fail1, efx_rc_t, rc);
684 __checkReturn efx_rc_t
688 __out_opt size_t *sizep,
689 __out_opt uint32_t *addressp,
690 __out_opt uint32_t *erase_sizep,
691 __out_opt uint32_t *write_sizep)
693 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
694 MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
698 (void) memset(payload, 0, sizeof (payload));
699 req.emr_cmd = MC_CMD_NVRAM_INFO;
700 req.emr_in_buf = payload;
701 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
702 req.emr_out_buf = payload;
703 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
705 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
707 efx_mcdi_execute_quiet(enp, &req);
709 if (req.emr_rc != 0) {
714 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
720 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
723 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
726 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
730 (req.emr_out_length_used <
731 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
732 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
740 EFSYS_PROBE1(fail1, efx_rc_t, rc);
746 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
747 * NVRAM updates. Older firmware will ignore the flags field in the request.
749 __checkReturn efx_rc_t
750 efx_mcdi_nvram_update_start(
754 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
755 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
759 (void) memset(payload, 0, sizeof (payload));
760 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
761 req.emr_in_buf = payload;
762 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
763 req.emr_out_buf = payload;
764 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
766 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
768 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
769 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
771 efx_mcdi_execute(enp, &req);
773 if (req.emr_rc != 0) {
781 EFSYS_PROBE1(fail1, efx_rc_t, rc);
786 __checkReturn efx_rc_t
790 __in uint32_t offset,
791 __out_bcount(size) caddr_t data,
796 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
797 MC_CMD_NVRAM_READ_OUT_LENMAX)];
800 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
805 (void) memset(payload, 0, sizeof (payload));
806 req.emr_cmd = MC_CMD_NVRAM_READ;
807 req.emr_in_buf = payload;
808 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
809 req.emr_out_buf = payload;
810 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
812 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
813 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
814 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
815 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
817 efx_mcdi_execute(enp, &req);
819 if (req.emr_rc != 0) {
824 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
830 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
838 EFSYS_PROBE1(fail1, efx_rc_t, rc);
843 __checkReturn efx_rc_t
844 efx_mcdi_nvram_erase(
847 __in uint32_t offset,
851 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
852 MC_CMD_NVRAM_ERASE_OUT_LEN)];
855 (void) memset(payload, 0, sizeof (payload));
856 req.emr_cmd = MC_CMD_NVRAM_ERASE;
857 req.emr_in_buf = payload;
858 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
859 req.emr_out_buf = payload;
860 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
862 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
863 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
864 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
866 efx_mcdi_execute(enp, &req);
868 if (req.emr_rc != 0) {
876 EFSYS_PROBE1(fail1, efx_rc_t, rc);
882 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
883 * Sienna and EF10 based boards. However EF10 based boards support the use
884 * of this command with payloads up to the maximum MCDI V2 payload length.
886 __checkReturn efx_rc_t
887 efx_mcdi_nvram_write(
890 __in uint32_t offset,
891 __out_bcount(size) caddr_t data,
895 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1,
896 MCDI_CTL_SDU_LEN_MAX_V2)];
898 size_t max_data_size;
900 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length
901 - MC_CMD_NVRAM_WRITE_IN_LEN(0);
902 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0);
903 EFSYS_ASSERT3U(max_data_size, <,
904 enp->en_nic_cfg.enc_mcdi_max_payload_length);
906 if (size > max_data_size) {
911 (void) memset(payload, 0, sizeof (payload));
912 req.emr_cmd = MC_CMD_NVRAM_WRITE;
913 req.emr_in_buf = payload;
914 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
915 req.emr_out_buf = payload;
916 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
918 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
919 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
920 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
922 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
925 efx_mcdi_execute(enp, &req);
927 if (req.emr_rc != 0) {
937 EFSYS_PROBE1(fail1, efx_rc_t, rc);
944 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
945 * NVRAM updates. Older firmware will ignore the flags field in the request.
947 __checkReturn efx_rc_t
948 efx_mcdi_nvram_update_finish(
951 __in boolean_t reboot,
952 __out_opt uint32_t *verify_resultp)
954 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
956 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
957 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)];
958 uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
961 (void) memset(payload, 0, sizeof (payload));
962 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
963 req.emr_in_buf = payload;
964 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
965 req.emr_out_buf = payload;
966 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
968 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
969 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
971 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
972 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
974 efx_mcdi_execute(enp, &req);
976 if (req.emr_rc != 0) {
981 if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
982 verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
983 if (encp->enc_nvram_update_verify_result_supported) {
984 /* Result of update verification is missing */
990 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
993 if ((encp->enc_nvram_update_verify_result_supported) &&
994 (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) {
995 /* Update verification failed */
1000 if (verify_resultp != NULL)
1001 *verify_resultp = verify_result;
1010 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1012 /* Always report verification result */
1013 if (verify_resultp != NULL)
1014 *verify_resultp = verify_result;
1021 __checkReturn efx_rc_t
1022 efx_mcdi_nvram_test(
1023 __in efx_nic_t *enp,
1024 __in uint32_t partn)
1027 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
1028 MC_CMD_NVRAM_TEST_OUT_LEN)];
1032 (void) memset(payload, 0, sizeof (payload));
1033 req.emr_cmd = MC_CMD_NVRAM_TEST;
1034 req.emr_in_buf = payload;
1035 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1036 req.emr_out_buf = payload;
1037 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1039 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1041 efx_mcdi_execute(enp, &req);
1043 if (req.emr_rc != 0) {
1048 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1053 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1054 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1056 EFSYS_PROBE1(nvram_test_failure, int, partn);
1069 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1074 #endif /* EFSYS_OPT_DIAG */
1077 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */