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_erase, /* envo_partn_erase */
47 siena_nvram_partn_write, /* envo_partn_write */
48 siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */
49 siena_nvram_partn_get_version, /* envo_partn_get_version */
50 siena_nvram_partn_set_version, /* envo_partn_set_version */
51 NULL, /* envo_partn_validate */
54 #endif /* EFSYS_OPT_SIENA */
56 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
58 static const efx_nvram_ops_t __efx_nvram_ef10_ops = {
60 ef10_nvram_test, /* envo_test */
61 #endif /* EFSYS_OPT_DIAG */
62 ef10_nvram_type_to_partn, /* envo_type_to_partn */
63 ef10_nvram_partn_size, /* envo_partn_size */
64 ef10_nvram_partn_rw_start, /* envo_partn_rw_start */
65 ef10_nvram_partn_read, /* envo_partn_read */
66 ef10_nvram_partn_erase, /* envo_partn_erase */
67 ef10_nvram_partn_write, /* envo_partn_write */
68 ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */
69 ef10_nvram_partn_get_version, /* envo_partn_get_version */
70 ef10_nvram_partn_set_version, /* envo_partn_set_version */
71 ef10_nvram_buffer_validate, /* envo_buffer_validate */
74 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
76 __checkReturn efx_rc_t
80 const efx_nvram_ops_t *envop;
83 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
84 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
85 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
87 switch (enp->en_family) {
89 case EFX_FAMILY_SIENA:
90 envop = &__efx_nvram_siena_ops;
92 #endif /* EFSYS_OPT_SIENA */
94 #if EFSYS_OPT_HUNTINGTON
95 case EFX_FAMILY_HUNTINGTON:
96 envop = &__efx_nvram_ef10_ops;
98 #endif /* EFSYS_OPT_HUNTINGTON */
100 #if EFSYS_OPT_MEDFORD
101 case EFX_FAMILY_MEDFORD:
102 envop = &__efx_nvram_ef10_ops;
104 #endif /* EFSYS_OPT_MEDFORD */
112 enp->en_envop = envop;
113 enp->en_mod_flags |= EFX_MOD_NVRAM;
118 EFSYS_PROBE1(fail1, efx_rc_t, rc);
125 __checkReturn efx_rc_t
129 const efx_nvram_ops_t *envop = enp->en_envop;
132 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
133 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
135 if ((rc = envop->envo_test(enp)) != 0)
141 EFSYS_PROBE1(fail1, efx_rc_t, rc);
146 #endif /* EFSYS_OPT_DIAG */
148 __checkReturn efx_rc_t
151 __in efx_nvram_type_t type,
154 const efx_nvram_ops_t *envop = enp->en_envop;
158 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
159 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
161 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
163 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
166 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
174 EFSYS_PROBE1(fail1, efx_rc_t, rc);
180 __checkReturn efx_rc_t
181 efx_nvram_get_version(
183 __in efx_nvram_type_t type,
184 __out uint32_t *subtypep,
185 __out_ecount(4) uint16_t version[4])
187 const efx_nvram_ops_t *envop = enp->en_envop;
191 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
192 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
193 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
195 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
197 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
200 if ((rc = envop->envo_partn_get_version(enp, partn,
201 subtypep, version)) != 0)
209 EFSYS_PROBE1(fail1, efx_rc_t, rc);
214 __checkReturn efx_rc_t
217 __in efx_nvram_type_t type,
218 __out_opt size_t *chunk_sizep)
220 const efx_nvram_ops_t *envop = enp->en_envop;
224 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
225 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
227 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
228 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
230 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
232 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
235 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
238 enp->en_nvram_locked = type;
245 EFSYS_PROBE1(fail1, efx_rc_t, rc);
250 __checkReturn efx_rc_t
251 efx_nvram_read_chunk(
253 __in efx_nvram_type_t type,
254 __in unsigned int offset,
255 __out_bcount(size) caddr_t data,
258 const efx_nvram_ops_t *envop = enp->en_envop;
262 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
263 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
265 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
266 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
268 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
270 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
273 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
281 EFSYS_PROBE1(fail1, efx_rc_t, rc);
286 __checkReturn efx_rc_t
289 __in efx_nvram_type_t type)
291 const efx_nvram_ops_t *envop = enp->en_envop;
292 unsigned int offset = 0;
297 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
298 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
300 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
301 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
303 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
305 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
308 if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
311 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
321 EFSYS_PROBE1(fail1, efx_rc_t, rc);
326 __checkReturn efx_rc_t
327 efx_nvram_write_chunk(
329 __in efx_nvram_type_t type,
330 __in unsigned int offset,
331 __in_bcount(size) caddr_t data,
334 const efx_nvram_ops_t *envop = enp->en_envop;
338 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
339 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
341 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
342 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
344 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
346 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
349 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
357 EFSYS_PROBE1(fail1, efx_rc_t, rc);
362 __checkReturn efx_rc_t
365 __in efx_nvram_type_t type)
367 const efx_nvram_ops_t *envop = enp->en_envop;
371 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
372 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
374 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
375 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
377 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
379 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
382 if ((rc = envop->envo_partn_rw_finish(enp, partn)) != 0)
385 enp->en_nvram_locked = EFX_NVRAM_INVALID;
391 enp->en_nvram_locked = EFX_NVRAM_INVALID;
394 EFSYS_PROBE1(fail1, efx_rc_t, rc);
399 __checkReturn efx_rc_t
400 efx_nvram_set_version(
402 __in efx_nvram_type_t type,
403 __in_ecount(4) uint16_t version[4])
405 const efx_nvram_ops_t *envop = enp->en_envop;
409 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
410 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
411 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
413 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
416 * The Siena implementation of envo_set_version() will attempt to
417 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
418 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
420 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
422 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
425 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
433 EFSYS_PROBE1(fail1, efx_rc_t, rc);
438 /* Validate buffer contents (before writing to flash) */
439 __checkReturn efx_rc_t
442 __in efx_nvram_type_t type,
443 __in_bcount(partn_size) caddr_t partn_data,
444 __in size_t partn_size)
446 const efx_nvram_ops_t *envop = enp->en_envop;
450 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
451 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
452 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
454 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
457 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
460 if (envop->envo_type_to_partn != NULL &&
461 ((rc = envop->envo_buffer_validate(enp, partn,
462 partn_data, partn_size)) != 0))
470 EFSYS_PROBE1(fail1, efx_rc_t, rc);
480 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
481 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
482 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
484 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
486 enp->en_envop = NULL;
487 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
490 #endif /* EFSYS_OPT_NVRAM */
492 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
495 * Internal MCDI request handling
498 __checkReturn efx_rc_t
499 efx_mcdi_nvram_partitions(
501 __out_bcount(size) caddr_t data,
503 __out unsigned int *npartnp)
506 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
507 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
511 (void) memset(payload, 0, sizeof (payload));
512 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
513 req.emr_in_buf = payload;
514 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
515 req.emr_out_buf = payload;
516 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
518 efx_mcdi_execute(enp, &req);
520 if (req.emr_rc != 0) {
525 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
529 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
531 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
536 if (size < npartn * sizeof (uint32_t)) {
544 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
545 (npartn * sizeof (uint32_t)));
554 EFSYS_PROBE1(fail1, efx_rc_t, rc);
559 __checkReturn efx_rc_t
560 efx_mcdi_nvram_metadata(
563 __out uint32_t *subtypep,
564 __out_ecount(4) uint16_t version[4],
565 __out_bcount_opt(size) char *descp,
569 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
570 MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
573 (void) memset(payload, 0, sizeof (payload));
574 req.emr_cmd = MC_CMD_NVRAM_METADATA;
575 req.emr_in_buf = payload;
576 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
577 req.emr_out_buf = payload;
578 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
580 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
582 efx_mcdi_execute(enp, &req);
584 if (req.emr_rc != 0) {
589 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
594 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
595 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
596 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
601 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
602 NVRAM_METADATA_OUT_VERSION_VALID)) {
603 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
604 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
605 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
606 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
608 version[0] = version[1] = version[2] = version[3] = 0;
611 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
612 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
613 /* Return optional descrition string */
614 if ((descp != NULL) && (size > 0)) {
618 desclen = (req.emr_out_length_used
619 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
621 EFSYS_ASSERT3U(desclen, <=,
622 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
624 if (size < desclen) {
629 memcpy(descp, MCDI_OUT2(req, char,
630 NVRAM_METADATA_OUT_DESCRIPTION),
633 /* Ensure string is NUL terminated */
634 descp[desclen] = '\0';
645 EFSYS_PROBE1(fail1, efx_rc_t, rc);
650 __checkReturn efx_rc_t
654 __out_opt size_t *sizep,
655 __out_opt uint32_t *addressp,
656 __out_opt uint32_t *erase_sizep,
657 __out_opt uint32_t *write_sizep)
659 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
660 MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
664 (void) memset(payload, 0, sizeof (payload));
665 req.emr_cmd = MC_CMD_NVRAM_INFO;
666 req.emr_in_buf = payload;
667 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
668 req.emr_out_buf = payload;
669 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
671 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
673 efx_mcdi_execute_quiet(enp, &req);
675 if (req.emr_rc != 0) {
680 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
686 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
689 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
692 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
696 (req.emr_out_length_used <
697 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
698 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
706 EFSYS_PROBE1(fail1, efx_rc_t, rc);
712 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
713 * NVRAM updates. Older firmware will ignore the flags field in the request.
715 __checkReturn efx_rc_t
716 efx_mcdi_nvram_update_start(
720 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
721 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
725 (void) memset(payload, 0, sizeof (payload));
726 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
727 req.emr_in_buf = payload;
728 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
729 req.emr_out_buf = payload;
730 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
732 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
734 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
735 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
737 efx_mcdi_execute(enp, &req);
739 if (req.emr_rc != 0) {
747 EFSYS_PROBE1(fail1, efx_rc_t, rc);
752 __checkReturn efx_rc_t
756 __in uint32_t offset,
757 __out_bcount(size) caddr_t data,
762 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
763 MC_CMD_NVRAM_READ_OUT_LENMAX)];
766 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
771 (void) memset(payload, 0, sizeof (payload));
772 req.emr_cmd = MC_CMD_NVRAM_READ;
773 req.emr_in_buf = payload;
774 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
775 req.emr_out_buf = payload;
776 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
778 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
779 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
780 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
781 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
783 efx_mcdi_execute(enp, &req);
785 if (req.emr_rc != 0) {
790 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
796 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
804 EFSYS_PROBE1(fail1, efx_rc_t, rc);
809 __checkReturn efx_rc_t
810 efx_mcdi_nvram_erase(
813 __in uint32_t offset,
817 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
818 MC_CMD_NVRAM_ERASE_OUT_LEN)];
821 (void) memset(payload, 0, sizeof (payload));
822 req.emr_cmd = MC_CMD_NVRAM_ERASE;
823 req.emr_in_buf = payload;
824 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
825 req.emr_out_buf = payload;
826 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
828 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
829 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
830 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
832 efx_mcdi_execute(enp, &req);
834 if (req.emr_rc != 0) {
842 EFSYS_PROBE1(fail1, efx_rc_t, rc);
848 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
849 * Sienna and EF10 based boards. However EF10 based boards support the use
850 * of this command with payloads up to the maximum MCDI V2 payload length.
852 __checkReturn efx_rc_t
853 efx_mcdi_nvram_write(
856 __in uint32_t offset,
857 __out_bcount(size) caddr_t data,
861 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1,
862 MCDI_CTL_SDU_LEN_MAX_V2)];
864 size_t max_data_size;
866 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length
867 - MC_CMD_NVRAM_WRITE_IN_LEN(0);
868 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0);
869 EFSYS_ASSERT3U(max_data_size, <,
870 enp->en_nic_cfg.enc_mcdi_max_payload_length);
872 if (size > max_data_size) {
877 (void) memset(payload, 0, sizeof (payload));
878 req.emr_cmd = MC_CMD_NVRAM_WRITE;
879 req.emr_in_buf = payload;
880 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
881 req.emr_out_buf = payload;
882 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
884 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
885 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
886 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
888 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
891 efx_mcdi_execute(enp, &req);
893 if (req.emr_rc != 0) {
903 EFSYS_PROBE1(fail1, efx_rc_t, rc);
910 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
911 * NVRAM updates. Older firmware will ignore the flags field in the request.
913 __checkReturn efx_rc_t
914 efx_mcdi_nvram_update_finish(
917 __in boolean_t reboot,
918 __out_opt uint32_t *resultp)
920 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
922 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
923 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)];
924 uint32_t result = 0; /* FIXME: use MC_CMD_NVRAM_VERIFY_RC_UNKNOWN */
927 (void) memset(payload, 0, sizeof (payload));
928 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
929 req.emr_in_buf = payload;
930 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
931 req.emr_out_buf = payload;
932 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
934 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
935 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
937 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
938 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
940 efx_mcdi_execute(enp, &req);
942 if (req.emr_rc != 0) {
947 if (encp->enc_fw_verified_nvram_update_required == B_FALSE) {
948 /* Report success if verified updates are not supported. */
949 result = MC_CMD_NVRAM_VERIFY_RC_SUCCESS;
951 /* Firmware-verified NVRAM updates are required */
952 if (req.emr_out_length_used <
953 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
958 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
960 if (result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) {
961 /* Mandatory verification failed */
977 EFSYS_PROBE1(fail1, efx_rc_t, rc);
979 /* Always report verification result */
988 __checkReturn efx_rc_t
994 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
995 MC_CMD_NVRAM_TEST_OUT_LEN)];
999 (void) memset(payload, 0, sizeof (payload));
1000 req.emr_cmd = MC_CMD_NVRAM_TEST;
1001 req.emr_in_buf = payload;
1002 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1003 req.emr_out_buf = payload;
1004 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1006 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1008 efx_mcdi_execute(enp, &req);
1010 if (req.emr_rc != 0) {
1015 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1020 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1021 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1023 EFSYS_PROBE1(nvram_test_failure, int, partn);
1036 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1041 #endif /* EFSYS_OPT_DIAG */
1044 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */