2 * Copyright (c) 2009-2016 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
38 static const efx_nvram_ops_t __efx_nvram_siena_ops = {
40 siena_nvram_test, /* envo_test */
41 #endif /* EFSYS_OPT_DIAG */
42 siena_nvram_type_to_partn, /* envo_type_to_partn */
43 siena_nvram_partn_size, /* envo_partn_size */
44 siena_nvram_partn_rw_start, /* envo_partn_rw_start */
45 siena_nvram_partn_read, /* envo_partn_read */
46 siena_nvram_partn_read, /* envo_partn_read_backup */
47 siena_nvram_partn_erase, /* envo_partn_erase */
48 siena_nvram_partn_write, /* envo_partn_write */
49 siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */
50 siena_nvram_partn_get_version, /* envo_partn_get_version */
51 siena_nvram_partn_set_version, /* envo_partn_set_version */
52 NULL, /* envo_partn_validate */
55 #endif /* EFSYS_OPT_SIENA */
57 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
59 static const efx_nvram_ops_t __efx_nvram_ef10_ops = {
61 ef10_nvram_test, /* envo_test */
62 #endif /* EFSYS_OPT_DIAG */
63 ef10_nvram_type_to_partn, /* envo_type_to_partn */
64 ef10_nvram_partn_size, /* envo_partn_size */
65 ef10_nvram_partn_rw_start, /* envo_partn_rw_start */
66 ef10_nvram_partn_read, /* envo_partn_read */
67 ef10_nvram_partn_read_backup, /* envo_partn_read_backup */
68 ef10_nvram_partn_erase, /* envo_partn_erase */
69 ef10_nvram_partn_write, /* envo_partn_write */
70 ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */
71 ef10_nvram_partn_get_version, /* envo_partn_get_version */
72 ef10_nvram_partn_set_version, /* envo_partn_set_version */
73 ef10_nvram_buffer_validate, /* envo_buffer_validate */
76 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
78 __checkReturn efx_rc_t
82 const efx_nvram_ops_t *envop;
85 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
86 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
87 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
89 switch (enp->en_family) {
91 case EFX_FAMILY_SIENA:
92 envop = &__efx_nvram_siena_ops;
94 #endif /* EFSYS_OPT_SIENA */
96 #if EFSYS_OPT_HUNTINGTON
97 case EFX_FAMILY_HUNTINGTON:
98 envop = &__efx_nvram_ef10_ops;
100 #endif /* EFSYS_OPT_HUNTINGTON */
102 #if EFSYS_OPT_MEDFORD
103 case EFX_FAMILY_MEDFORD:
104 envop = &__efx_nvram_ef10_ops;
106 #endif /* EFSYS_OPT_MEDFORD */
114 enp->en_envop = envop;
115 enp->en_mod_flags |= EFX_MOD_NVRAM;
117 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
122 EFSYS_PROBE1(fail1, efx_rc_t, rc);
129 __checkReturn efx_rc_t
133 const efx_nvram_ops_t *envop = enp->en_envop;
136 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
137 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
139 if ((rc = envop->envo_test(enp)) != 0)
145 EFSYS_PROBE1(fail1, efx_rc_t, rc);
150 #endif /* EFSYS_OPT_DIAG */
152 __checkReturn efx_rc_t
155 __in efx_nvram_type_t type,
158 const efx_nvram_ops_t *envop = enp->en_envop;
162 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
163 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
165 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
167 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
170 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
178 EFSYS_PROBE1(fail1, efx_rc_t, rc);
184 __checkReturn efx_rc_t
185 efx_nvram_get_version(
187 __in efx_nvram_type_t type,
188 __out uint32_t *subtypep,
189 __out_ecount(4) uint16_t version[4])
191 const efx_nvram_ops_t *envop = enp->en_envop;
195 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
196 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
197 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
199 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
201 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
204 if ((rc = envop->envo_partn_get_version(enp, partn,
205 subtypep, version)) != 0)
213 EFSYS_PROBE1(fail1, efx_rc_t, rc);
218 __checkReturn efx_rc_t
221 __in efx_nvram_type_t type,
222 __out_opt size_t *chunk_sizep)
224 const efx_nvram_ops_t *envop = enp->en_envop;
228 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
229 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
231 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
232 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
234 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
237 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
239 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
242 enp->en_nvram_partn_locked = partn;
249 EFSYS_PROBE1(fail1, efx_rc_t, rc);
254 __checkReturn efx_rc_t
255 efx_nvram_read_chunk(
257 __in efx_nvram_type_t type,
258 __in unsigned int offset,
259 __out_bcount(size) caddr_t data,
262 const efx_nvram_ops_t *envop = enp->en_envop;
266 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
267 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
269 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
270 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
272 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
275 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
277 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
285 EFSYS_PROBE1(fail1, efx_rc_t, rc);
291 * Read from the backup (writeable) store of an A/B partition.
292 * For non A/B partitions, there is only a single store, and so this
293 * function has the same behaviour as efx_nvram_read_chunk().
295 __checkReturn efx_rc_t
296 efx_nvram_read_backup(
298 __in efx_nvram_type_t type,
299 __in unsigned int offset,
300 __out_bcount(size) caddr_t data,
303 const efx_nvram_ops_t *envop = enp->en_envop;
307 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
308 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
310 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
311 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
313 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
316 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
318 if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
327 EFSYS_PROBE1(fail1, efx_rc_t, rc);
332 __checkReturn efx_rc_t
335 __in efx_nvram_type_t type)
337 const efx_nvram_ops_t *envop = enp->en_envop;
338 unsigned int offset = 0;
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 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
352 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
354 if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
357 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
367 EFSYS_PROBE1(fail1, efx_rc_t, rc);
372 __checkReturn efx_rc_t
373 efx_nvram_write_chunk(
375 __in efx_nvram_type_t type,
376 __in unsigned int offset,
377 __in_bcount(size) caddr_t data,
380 const efx_nvram_ops_t *envop = enp->en_envop;
384 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
385 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
387 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
388 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
390 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
393 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
395 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
403 EFSYS_PROBE1(fail1, efx_rc_t, rc);
408 __checkReturn efx_rc_t
411 __in efx_nvram_type_t type,
412 __out_opt uint32_t *verify_resultp)
414 const efx_nvram_ops_t *envop = enp->en_envop;
416 uint32_t verify_result = 0;
419 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
420 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
422 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
423 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
425 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
428 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
430 if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0)
433 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
435 if (verify_resultp != NULL)
436 *verify_resultp = verify_result;
442 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
445 EFSYS_PROBE1(fail1, efx_rc_t, rc);
447 /* Always report verification result */
448 if (verify_resultp != NULL)
449 *verify_resultp = verify_result;
454 __checkReturn efx_rc_t
455 efx_nvram_set_version(
457 __in efx_nvram_type_t type,
458 __in_ecount(4) uint16_t version[4])
460 const efx_nvram_ops_t *envop = enp->en_envop;
464 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
465 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
466 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
468 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
470 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
474 * The Siena implementation of envo_set_version() will attempt to
475 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition.
476 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
478 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
480 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
488 EFSYS_PROBE1(fail1, efx_rc_t, rc);
493 /* Validate buffer contents (before writing to flash) */
494 __checkReturn efx_rc_t
497 __in efx_nvram_type_t type,
498 __in_bcount(partn_size) caddr_t partn_data,
499 __in size_t partn_size)
501 const efx_nvram_ops_t *envop = enp->en_envop;
505 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
506 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
507 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
509 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
512 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
515 if (envop->envo_buffer_validate != NULL) {
516 if ((rc = envop->envo_buffer_validate(enp, partn,
517 partn_data, partn_size)) != 0)
526 EFSYS_PROBE1(fail1, efx_rc_t, rc);
536 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
537 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
538 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
540 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
542 enp->en_envop = NULL;
543 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
546 #endif /* EFSYS_OPT_NVRAM */
548 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
551 * Internal MCDI request handling
554 __checkReturn efx_rc_t
555 efx_mcdi_nvram_partitions(
557 __out_bcount(size) caddr_t data,
559 __out unsigned int *npartnp)
562 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
563 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
567 (void) memset(payload, 0, sizeof (payload));
568 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
569 req.emr_in_buf = payload;
570 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
571 req.emr_out_buf = payload;
572 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
574 efx_mcdi_execute(enp, &req);
576 if (req.emr_rc != 0) {
581 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
585 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
587 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
592 if (size < npartn * sizeof (uint32_t)) {
600 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
601 (npartn * sizeof (uint32_t)));
610 EFSYS_PROBE1(fail1, efx_rc_t, rc);
615 __checkReturn efx_rc_t
616 efx_mcdi_nvram_metadata(
619 __out uint32_t *subtypep,
620 __out_ecount(4) uint16_t version[4],
621 __out_bcount_opt(size) char *descp,
625 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
626 MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
629 (void) memset(payload, 0, sizeof (payload));
630 req.emr_cmd = MC_CMD_NVRAM_METADATA;
631 req.emr_in_buf = payload;
632 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
633 req.emr_out_buf = payload;
634 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
636 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
638 efx_mcdi_execute(enp, &req);
640 if (req.emr_rc != 0) {
645 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
650 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
651 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
652 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
657 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
658 NVRAM_METADATA_OUT_VERSION_VALID)) {
659 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
660 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
661 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
662 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
664 version[0] = version[1] = version[2] = version[3] = 0;
667 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
668 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
669 /* Return optional descrition string */
670 if ((descp != NULL) && (size > 0)) {
674 desclen = (req.emr_out_length_used
675 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
677 EFSYS_ASSERT3U(desclen, <=,
678 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
680 if (size < desclen) {
685 memcpy(descp, MCDI_OUT2(req, char,
686 NVRAM_METADATA_OUT_DESCRIPTION),
689 /* Ensure string is NUL terminated */
690 descp[desclen] = '\0';
701 EFSYS_PROBE1(fail1, efx_rc_t, rc);
706 __checkReturn efx_rc_t
710 __out_opt size_t *sizep,
711 __out_opt uint32_t *addressp,
712 __out_opt uint32_t *erase_sizep,
713 __out_opt uint32_t *write_sizep)
715 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
716 MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
720 (void) memset(payload, 0, sizeof (payload));
721 req.emr_cmd = MC_CMD_NVRAM_INFO;
722 req.emr_in_buf = payload;
723 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
724 req.emr_out_buf = payload;
725 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
727 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
729 efx_mcdi_execute_quiet(enp, &req);
731 if (req.emr_rc != 0) {
736 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
742 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
745 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
748 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
752 (req.emr_out_length_used <
753 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
754 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
762 EFSYS_PROBE1(fail1, efx_rc_t, rc);
768 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
769 * NVRAM updates. Older firmware will ignore the flags field in the request.
771 __checkReturn efx_rc_t
772 efx_mcdi_nvram_update_start(
776 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
777 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
781 (void) memset(payload, 0, sizeof (payload));
782 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
783 req.emr_in_buf = payload;
784 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
785 req.emr_out_buf = payload;
786 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
788 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
790 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
791 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
793 efx_mcdi_execute(enp, &req);
795 if (req.emr_rc != 0) {
803 EFSYS_PROBE1(fail1, efx_rc_t, rc);
808 __checkReturn efx_rc_t
812 __in uint32_t offset,
813 __out_bcount(size) caddr_t data,
818 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
819 MC_CMD_NVRAM_READ_OUT_LENMAX)];
822 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
827 (void) memset(payload, 0, sizeof (payload));
828 req.emr_cmd = MC_CMD_NVRAM_READ;
829 req.emr_in_buf = payload;
830 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
831 req.emr_out_buf = payload;
832 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
834 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
835 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
836 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
837 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
839 efx_mcdi_execute(enp, &req);
841 if (req.emr_rc != 0) {
846 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
852 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
860 EFSYS_PROBE1(fail1, efx_rc_t, rc);
865 __checkReturn efx_rc_t
866 efx_mcdi_nvram_erase(
869 __in uint32_t offset,
873 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
874 MC_CMD_NVRAM_ERASE_OUT_LEN)];
877 (void) memset(payload, 0, sizeof (payload));
878 req.emr_cmd = MC_CMD_NVRAM_ERASE;
879 req.emr_in_buf = payload;
880 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
881 req.emr_out_buf = payload;
882 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
884 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
885 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
886 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
888 efx_mcdi_execute(enp, &req);
890 if (req.emr_rc != 0) {
898 EFSYS_PROBE1(fail1, efx_rc_t, rc);
904 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
905 * Sienna and EF10 based boards. However EF10 based boards support the use
906 * of this command with payloads up to the maximum MCDI V2 payload length.
908 __checkReturn efx_rc_t
909 efx_mcdi_nvram_write(
912 __in uint32_t offset,
913 __out_bcount(size) caddr_t data,
917 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1,
918 MCDI_CTL_SDU_LEN_MAX_V2)];
920 size_t max_data_size;
922 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length
923 - MC_CMD_NVRAM_WRITE_IN_LEN(0);
924 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0);
925 EFSYS_ASSERT3U(max_data_size, <,
926 enp->en_nic_cfg.enc_mcdi_max_payload_length);
928 if (size > max_data_size) {
933 (void) memset(payload, 0, sizeof (payload));
934 req.emr_cmd = MC_CMD_NVRAM_WRITE;
935 req.emr_in_buf = payload;
936 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
937 req.emr_out_buf = payload;
938 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
940 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
941 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
942 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
944 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
947 efx_mcdi_execute(enp, &req);
949 if (req.emr_rc != 0) {
959 EFSYS_PROBE1(fail1, efx_rc_t, rc);
966 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
967 * NVRAM updates. Older firmware will ignore the flags field in the request.
969 __checkReturn efx_rc_t
970 efx_mcdi_nvram_update_finish(
973 __in boolean_t reboot,
974 __out_opt uint32_t *verify_resultp)
976 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
978 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
979 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)];
980 uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
983 (void) memset(payload, 0, sizeof (payload));
984 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
985 req.emr_in_buf = payload;
986 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
987 req.emr_out_buf = payload;
988 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
990 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
991 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
993 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
994 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
996 efx_mcdi_execute(enp, &req);
998 if (req.emr_rc != 0) {
1003 if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
1004 verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
1005 if (encp->enc_nvram_update_verify_result_supported) {
1006 /* Result of update verification is missing */
1012 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
1015 if ((encp->enc_nvram_update_verify_result_supported) &&
1016 (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) {
1017 /* Update verification failed */
1022 if (verify_resultp != NULL)
1023 *verify_resultp = verify_result;
1032 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1034 /* Always report verification result */
1035 if (verify_resultp != NULL)
1036 *verify_resultp = verify_result;
1043 __checkReturn efx_rc_t
1044 efx_mcdi_nvram_test(
1045 __in efx_nic_t *enp,
1046 __in uint32_t partn)
1049 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
1050 MC_CMD_NVRAM_TEST_OUT_LEN)];
1054 (void) memset(payload, 0, sizeof (payload));
1055 req.emr_cmd = MC_CMD_NVRAM_TEST;
1056 req.emr_in_buf = payload;
1057 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1058 req.emr_out_buf = payload;
1059 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1061 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1063 efx_mcdi_execute(enp, &req);
1065 if (req.emr_rc != 0) {
1070 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1075 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1076 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1078 EFSYS_PROBE1(nvram_test_failure, int, partn);
1091 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1096 #endif /* EFSYS_OPT_DIAG */
1099 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */