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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
41 static const efx_nvram_ops_t __efx_nvram_siena_ops = {
43 siena_nvram_test, /* envo_test */
44 #endif /* EFSYS_OPT_DIAG */
45 siena_nvram_type_to_partn, /* envo_type_to_partn */
46 siena_nvram_partn_size, /* envo_partn_size */
47 siena_nvram_partn_rw_start, /* envo_partn_rw_start */
48 siena_nvram_partn_read, /* envo_partn_read */
49 siena_nvram_partn_erase, /* envo_partn_erase */
50 siena_nvram_partn_write, /* envo_partn_write */
51 siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */
52 siena_nvram_partn_get_version, /* envo_partn_get_version */
53 siena_nvram_partn_set_version, /* envo_partn_set_version */
54 NULL, /* envo_partn_validate */
57 #endif /* EFSYS_OPT_SIENA */
59 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
61 static const efx_nvram_ops_t __efx_nvram_ef10_ops = {
63 ef10_nvram_test, /* envo_test */
64 #endif /* EFSYS_OPT_DIAG */
65 ef10_nvram_type_to_partn, /* envo_type_to_partn */
66 ef10_nvram_partn_size, /* envo_partn_size */
67 ef10_nvram_partn_rw_start, /* envo_partn_rw_start */
68 ef10_nvram_partn_read, /* envo_partn_read */
69 ef10_nvram_partn_erase, /* envo_partn_erase */
70 ef10_nvram_partn_write, /* envo_partn_write */
71 ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */
72 ef10_nvram_partn_get_version, /* envo_partn_get_version */
73 ef10_nvram_partn_set_version, /* envo_partn_set_version */
74 ef10_nvram_buffer_validate, /* envo_buffer_validate */
77 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
79 __checkReturn efx_rc_t
83 const efx_nvram_ops_t *envop;
86 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
87 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
88 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
90 switch (enp->en_family) {
92 case EFX_FAMILY_SIENA:
93 envop = &__efx_nvram_siena_ops;
95 #endif /* EFSYS_OPT_SIENA */
97 #if EFSYS_OPT_HUNTINGTON
98 case EFX_FAMILY_HUNTINGTON:
99 envop = &__efx_nvram_ef10_ops;
101 #endif /* EFSYS_OPT_HUNTINGTON */
103 #if EFSYS_OPT_MEDFORD
104 case EFX_FAMILY_MEDFORD:
105 envop = &__efx_nvram_ef10_ops;
107 #endif /* EFSYS_OPT_MEDFORD */
115 enp->en_envop = envop;
116 enp->en_mod_flags |= EFX_MOD_NVRAM;
121 EFSYS_PROBE1(fail1, efx_rc_t, rc);
128 __checkReturn efx_rc_t
132 const efx_nvram_ops_t *envop = enp->en_envop;
135 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
136 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
138 if ((rc = envop->envo_test(enp)) != 0)
144 EFSYS_PROBE1(fail1, efx_rc_t, rc);
149 #endif /* EFSYS_OPT_DIAG */
151 __checkReturn efx_rc_t
154 __in efx_nvram_type_t type,
157 const efx_nvram_ops_t *envop = enp->en_envop;
161 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
162 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
164 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
166 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
169 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
177 EFSYS_PROBE1(fail1, efx_rc_t, rc);
183 __checkReturn efx_rc_t
184 efx_nvram_get_version(
186 __in efx_nvram_type_t type,
187 __out uint32_t *subtypep,
188 __out_ecount(4) uint16_t version[4])
190 const efx_nvram_ops_t *envop = enp->en_envop;
194 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
195 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
196 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
198 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
200 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
203 if ((rc = envop->envo_partn_get_version(enp, partn,
204 subtypep, version)) != 0)
212 EFSYS_PROBE1(fail1, efx_rc_t, rc);
217 __checkReturn efx_rc_t
220 __in efx_nvram_type_t type,
221 __out_opt size_t *chunk_sizep)
223 const efx_nvram_ops_t *envop = enp->en_envop;
227 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
228 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
230 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
231 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
233 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
235 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
238 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
241 enp->en_nvram_locked = type;
248 EFSYS_PROBE1(fail1, efx_rc_t, rc);
253 __checkReturn efx_rc_t
254 efx_nvram_read_chunk(
256 __in efx_nvram_type_t type,
257 __in unsigned int offset,
258 __out_bcount(size) caddr_t data,
261 const efx_nvram_ops_t *envop = enp->en_envop;
265 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
266 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
268 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
269 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
271 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
273 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
276 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
284 EFSYS_PROBE1(fail1, efx_rc_t, rc);
289 __checkReturn efx_rc_t
292 __in efx_nvram_type_t type)
294 const efx_nvram_ops_t *envop = enp->en_envop;
295 unsigned int offset = 0;
300 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
301 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
303 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
304 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
306 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
308 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
311 if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
314 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
324 EFSYS_PROBE1(fail1, efx_rc_t, rc);
329 __checkReturn efx_rc_t
330 efx_nvram_write_chunk(
332 __in efx_nvram_type_t type,
333 __in unsigned int offset,
334 __in_bcount(size) caddr_t data,
337 const efx_nvram_ops_t *envop = enp->en_envop;
341 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
342 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
344 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
345 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
347 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
349 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
352 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
360 EFSYS_PROBE1(fail1, efx_rc_t, rc);
365 __checkReturn efx_rc_t
368 __in efx_nvram_type_t type)
370 const efx_nvram_ops_t *envop = enp->en_envop;
374 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
375 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
377 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
378 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
380 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
382 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
385 if ((rc = envop->envo_partn_rw_finish(enp, partn)) != 0)
388 enp->en_nvram_locked = EFX_NVRAM_INVALID;
394 enp->en_nvram_locked = EFX_NVRAM_INVALID;
397 EFSYS_PROBE1(fail1, efx_rc_t, rc);
402 __checkReturn efx_rc_t
403 efx_nvram_set_version(
405 __in efx_nvram_type_t type,
406 __in_ecount(4) uint16_t version[4])
408 const efx_nvram_ops_t *envop = enp->en_envop;
412 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
413 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
414 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
416 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
419 * The Siena implementation of envo_set_version() will attempt to
420 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
421 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
423 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
425 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
428 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
436 EFSYS_PROBE1(fail1, efx_rc_t, rc);
441 /* Validate buffer contents (before writing to flash) */
442 __checkReturn efx_rc_t
445 __in efx_nvram_type_t type,
446 __in_bcount(partn_size) caddr_t partn_data,
447 __in size_t partn_size)
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 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
460 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
463 if (envop->envo_type_to_partn != NULL &&
464 ((rc = envop->envo_buffer_validate(enp, partn,
465 partn_data, partn_size)) != 0))
473 EFSYS_PROBE1(fail1, efx_rc_t, rc);
483 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
484 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
485 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
487 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
489 enp->en_envop = NULL;
490 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
493 #endif /* EFSYS_OPT_NVRAM */
495 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
498 * Internal MCDI request handling
501 __checkReturn efx_rc_t
502 efx_mcdi_nvram_partitions(
504 __out_bcount(size) caddr_t data,
506 __out unsigned int *npartnp)
509 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
510 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
514 (void) memset(payload, 0, sizeof (payload));
515 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
516 req.emr_in_buf = payload;
517 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
518 req.emr_out_buf = payload;
519 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
521 efx_mcdi_execute(enp, &req);
523 if (req.emr_rc != 0) {
528 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
532 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
534 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
539 if (size < npartn * sizeof (uint32_t)) {
547 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
548 (npartn * sizeof (uint32_t)));
557 EFSYS_PROBE1(fail1, efx_rc_t, rc);
562 __checkReturn efx_rc_t
563 efx_mcdi_nvram_metadata(
566 __out uint32_t *subtypep,
567 __out_ecount(4) uint16_t version[4],
568 __out_bcount_opt(size) char *descp,
572 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
573 MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
576 (void) memset(payload, 0, sizeof (payload));
577 req.emr_cmd = MC_CMD_NVRAM_METADATA;
578 req.emr_in_buf = payload;
579 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
580 req.emr_out_buf = payload;
581 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
583 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
585 efx_mcdi_execute(enp, &req);
587 if (req.emr_rc != 0) {
592 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
597 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
598 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
599 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
604 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
605 NVRAM_METADATA_OUT_VERSION_VALID)) {
606 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
607 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
608 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
609 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
611 version[0] = version[1] = version[2] = version[3] = 0;
614 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
615 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
616 /* Return optional descrition string */
617 if ((descp != NULL) && (size > 0)) {
621 desclen = (req.emr_out_length_used
622 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
624 EFSYS_ASSERT3U(desclen, <=,
625 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
627 if (size < desclen) {
632 memcpy(descp, MCDI_OUT2(req, char,
633 NVRAM_METADATA_OUT_DESCRIPTION),
636 /* Ensure string is NUL terminated */
637 descp[desclen] = '\0';
648 EFSYS_PROBE1(fail1, efx_rc_t, rc);
653 __checkReturn efx_rc_t
657 __out_opt size_t *sizep,
658 __out_opt uint32_t *addressp,
659 __out_opt uint32_t *erase_sizep,
660 __out_opt uint32_t *write_sizep)
662 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
663 MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
667 (void) memset(payload, 0, sizeof (payload));
668 req.emr_cmd = MC_CMD_NVRAM_INFO;
669 req.emr_in_buf = payload;
670 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
671 req.emr_out_buf = payload;
672 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
674 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
676 efx_mcdi_execute_quiet(enp, &req);
678 if (req.emr_rc != 0) {
683 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
689 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
692 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
695 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
699 (req.emr_out_length_used <
700 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
701 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
709 EFSYS_PROBE1(fail1, efx_rc_t, rc);
715 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
716 * NVRAM updates. Older firmware will ignore the flags field in the request.
718 __checkReturn efx_rc_t
719 efx_mcdi_nvram_update_start(
723 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
724 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
728 (void) memset(payload, 0, sizeof (payload));
729 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
730 req.emr_in_buf = payload;
731 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
732 req.emr_out_buf = payload;
733 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
735 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
737 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
738 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
740 efx_mcdi_execute(enp, &req);
742 if (req.emr_rc != 0) {
750 EFSYS_PROBE1(fail1, efx_rc_t, rc);
755 __checkReturn efx_rc_t
759 __in uint32_t offset,
760 __out_bcount(size) caddr_t data,
765 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
766 MC_CMD_NVRAM_READ_OUT_LENMAX)];
769 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
774 (void) memset(payload, 0, sizeof (payload));
775 req.emr_cmd = MC_CMD_NVRAM_READ;
776 req.emr_in_buf = payload;
777 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
778 req.emr_out_buf = payload;
779 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
781 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
782 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
783 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
784 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
786 efx_mcdi_execute(enp, &req);
788 if (req.emr_rc != 0) {
793 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
799 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
807 EFSYS_PROBE1(fail1, efx_rc_t, rc);
812 __checkReturn efx_rc_t
813 efx_mcdi_nvram_erase(
816 __in uint32_t offset,
820 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
821 MC_CMD_NVRAM_ERASE_OUT_LEN)];
824 (void) memset(payload, 0, sizeof (payload));
825 req.emr_cmd = MC_CMD_NVRAM_ERASE;
826 req.emr_in_buf = payload;
827 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
828 req.emr_out_buf = payload;
829 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
831 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
832 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
833 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
835 efx_mcdi_execute(enp, &req);
837 if (req.emr_rc != 0) {
845 EFSYS_PROBE1(fail1, efx_rc_t, rc);
851 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
852 * Sienna and EF10 based boards. However EF10 based boards support the use
853 * of this command with payloads up to the maximum MCDI V2 payload length.
855 __checkReturn efx_rc_t
856 efx_mcdi_nvram_write(
859 __in uint32_t offset,
860 __out_bcount(size) caddr_t data,
864 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1,
865 MCDI_CTL_SDU_LEN_MAX_V2)];
867 size_t max_data_size;
869 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length
870 - MC_CMD_NVRAM_WRITE_IN_LEN(0);
871 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0);
872 EFSYS_ASSERT3U(max_data_size, <,
873 enp->en_nic_cfg.enc_mcdi_max_payload_length);
875 if (size > max_data_size) {
880 (void) memset(payload, 0, sizeof (payload));
881 req.emr_cmd = MC_CMD_NVRAM_WRITE;
882 req.emr_in_buf = payload;
883 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
884 req.emr_out_buf = payload;
885 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
887 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
888 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
889 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
891 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
894 efx_mcdi_execute(enp, &req);
896 if (req.emr_rc != 0) {
906 EFSYS_PROBE1(fail1, efx_rc_t, rc);
913 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
914 * NVRAM updates. Older firmware will ignore the flags field in the request.
916 __checkReturn efx_rc_t
917 efx_mcdi_nvram_update_finish(
920 __in boolean_t reboot,
921 __out_opt uint32_t *resultp)
923 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
925 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
926 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)];
927 uint32_t result = 0; /* FIXME: use MC_CMD_NVRAM_VERIFY_RC_UNKNOWN */
930 (void) memset(payload, 0, sizeof (payload));
931 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
932 req.emr_in_buf = payload;
933 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
934 req.emr_out_buf = payload;
935 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
937 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
938 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
940 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
941 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
943 efx_mcdi_execute(enp, &req);
945 if (req.emr_rc != 0) {
950 if (encp->enc_fw_verified_nvram_update_required == B_FALSE) {
951 /* Report success if verified updates are not supported. */
952 result = MC_CMD_NVRAM_VERIFY_RC_SUCCESS;
954 /* Firmware-verified NVRAM updates are required */
955 if (req.emr_out_length_used <
956 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
961 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
963 if (result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) {
964 /* Mandatory verification failed */
980 EFSYS_PROBE1(fail1, efx_rc_t, rc);
982 /* Always report verification result */
991 __checkReturn efx_rc_t
997 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
998 MC_CMD_NVRAM_TEST_OUT_LEN)];
1002 (void) memset(payload, 0, sizeof (payload));
1003 req.emr_cmd = MC_CMD_NVRAM_TEST;
1004 req.emr_in_buf = payload;
1005 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1006 req.emr_out_buf = payload;
1007 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1009 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1011 efx_mcdi_execute(enp, &req);
1013 if (req.emr_rc != 0) {
1018 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1023 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1024 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1026 EFSYS_PROBE1(nvram_test_failure, int, partn);
1039 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1044 #endif /* EFSYS_OPT_DIAG */
1047 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */