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 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
168 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
176 EFSYS_PROBE1(fail1, efx_rc_t, rc);
182 __checkReturn efx_rc_t
183 efx_nvram_get_version(
185 __in efx_nvram_type_t type,
186 __out uint32_t *subtypep,
187 __out_ecount(4) uint16_t version[4])
189 const efx_nvram_ops_t *envop = enp->en_envop;
193 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
194 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
195 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
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 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
230 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
232 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
235 enp->en_nvram_partn_locked = partn;
242 EFSYS_PROBE1(fail1, efx_rc_t, rc);
247 __checkReturn efx_rc_t
248 efx_nvram_read_chunk(
250 __in efx_nvram_type_t type,
251 __in unsigned int offset,
252 __out_bcount(size) caddr_t data,
255 const efx_nvram_ops_t *envop = enp->en_envop;
259 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
260 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
262 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
265 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
267 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
275 EFSYS_PROBE1(fail1, efx_rc_t, rc);
281 * Read from the backup (writeable) store of an A/B partition.
282 * For non A/B partitions, there is only a single store, and so this
283 * function has the same behaviour as efx_nvram_read_chunk().
285 __checkReturn efx_rc_t
286 efx_nvram_read_backup(
288 __in efx_nvram_type_t type,
289 __in unsigned int offset,
290 __out_bcount(size) caddr_t data,
293 const efx_nvram_ops_t *envop = enp->en_envop;
297 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
298 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
300 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
303 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
305 if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
314 EFSYS_PROBE1(fail1, efx_rc_t, rc);
319 __checkReturn efx_rc_t
322 __in efx_nvram_type_t type)
324 const efx_nvram_ops_t *envop = enp->en_envop;
325 unsigned int offset = 0;
330 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
331 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
333 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
336 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
338 if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
341 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
351 EFSYS_PROBE1(fail1, efx_rc_t, rc);
356 __checkReturn efx_rc_t
357 efx_nvram_write_chunk(
359 __in efx_nvram_type_t type,
360 __in unsigned int offset,
361 __in_bcount(size) caddr_t data,
364 const efx_nvram_ops_t *envop = enp->en_envop;
368 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
369 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
371 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
374 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
376 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
384 EFSYS_PROBE1(fail1, efx_rc_t, rc);
389 __checkReturn efx_rc_t
392 __in efx_nvram_type_t type,
393 __out_opt uint32_t *verify_resultp)
395 const efx_nvram_ops_t *envop = enp->en_envop;
397 uint32_t verify_result = 0;
400 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
401 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
403 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
406 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
408 if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0)
411 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
413 if (verify_resultp != NULL)
414 *verify_resultp = verify_result;
420 enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
423 EFSYS_PROBE1(fail1, efx_rc_t, rc);
425 /* Always report verification result */
426 if (verify_resultp != NULL)
427 *verify_resultp = verify_result;
432 __checkReturn efx_rc_t
433 efx_nvram_set_version(
435 __in efx_nvram_type_t type,
436 __in_ecount(4) uint16_t version[4])
438 const efx_nvram_ops_t *envop = enp->en_envop;
442 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
443 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
444 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
446 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
450 * The Siena implementation of envo_set_version() will attempt to
451 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition.
452 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
454 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
456 if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
464 EFSYS_PROBE1(fail1, efx_rc_t, rc);
469 /* Validate buffer contents (before writing to flash) */
470 __checkReturn efx_rc_t
473 __in efx_nvram_type_t type,
474 __in_bcount(partn_size) caddr_t partn_data,
475 __in size_t partn_size)
477 const efx_nvram_ops_t *envop = enp->en_envop;
481 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
482 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
483 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
485 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
488 if (envop->envo_buffer_validate != NULL) {
489 if ((rc = envop->envo_buffer_validate(enp, partn,
490 partn_data, partn_size)) != 0)
499 EFSYS_PROBE1(fail1, efx_rc_t, rc);
509 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
510 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
511 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
513 EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
515 enp->en_envop = NULL;
516 enp->en_mod_flags &= ~EFX_MOD_NVRAM;
519 #endif /* EFSYS_OPT_NVRAM */
521 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
524 * Internal MCDI request handling
527 __checkReturn efx_rc_t
528 efx_mcdi_nvram_partitions(
530 __out_bcount(size) caddr_t data,
532 __out unsigned int *npartnp)
535 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
536 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
540 (void) memset(payload, 0, sizeof (payload));
541 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
542 req.emr_in_buf = payload;
543 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
544 req.emr_out_buf = payload;
545 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
547 efx_mcdi_execute(enp, &req);
549 if (req.emr_rc != 0) {
554 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
558 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
560 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
565 if (size < npartn * sizeof (uint32_t)) {
573 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
574 (npartn * sizeof (uint32_t)));
583 EFSYS_PROBE1(fail1, efx_rc_t, rc);
588 __checkReturn efx_rc_t
589 efx_mcdi_nvram_metadata(
592 __out uint32_t *subtypep,
593 __out_ecount(4) uint16_t version[4],
594 __out_bcount_opt(size) char *descp,
598 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
599 MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
602 (void) memset(payload, 0, sizeof (payload));
603 req.emr_cmd = MC_CMD_NVRAM_METADATA;
604 req.emr_in_buf = payload;
605 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
606 req.emr_out_buf = payload;
607 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
609 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
611 efx_mcdi_execute_quiet(enp, &req);
613 if (req.emr_rc != 0) {
618 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
623 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
624 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
625 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
630 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
631 NVRAM_METADATA_OUT_VERSION_VALID)) {
632 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
633 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
634 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
635 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
637 version[0] = version[1] = version[2] = version[3] = 0;
640 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
641 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
642 /* Return optional descrition string */
643 if ((descp != NULL) && (size > 0)) {
647 desclen = (req.emr_out_length_used
648 - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
650 EFSYS_ASSERT3U(desclen, <=,
651 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
653 if (size < desclen) {
658 memcpy(descp, MCDI_OUT2(req, char,
659 NVRAM_METADATA_OUT_DESCRIPTION),
662 /* Ensure string is NUL terminated */
663 descp[desclen] = '\0';
674 EFSYS_PROBE1(fail1, efx_rc_t, rc);
679 __checkReturn efx_rc_t
683 __out_opt size_t *sizep,
684 __out_opt uint32_t *addressp,
685 __out_opt uint32_t *erase_sizep,
686 __out_opt uint32_t *write_sizep)
688 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
689 MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
693 (void) memset(payload, 0, sizeof (payload));
694 req.emr_cmd = MC_CMD_NVRAM_INFO;
695 req.emr_in_buf = payload;
696 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
697 req.emr_out_buf = payload;
698 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
700 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
702 efx_mcdi_execute_quiet(enp, &req);
704 if (req.emr_rc != 0) {
709 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
715 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
718 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
721 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
725 (req.emr_out_length_used <
726 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
727 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
735 EFSYS_PROBE1(fail1, efx_rc_t, rc);
741 * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
742 * NVRAM updates. Older firmware will ignore the flags field in the request.
744 __checkReturn efx_rc_t
745 efx_mcdi_nvram_update_start(
749 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
750 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
754 (void) memset(payload, 0, sizeof (payload));
755 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
756 req.emr_in_buf = payload;
757 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
758 req.emr_out_buf = payload;
759 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
761 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
763 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
764 NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
766 efx_mcdi_execute(enp, &req);
768 if (req.emr_rc != 0) {
776 EFSYS_PROBE1(fail1, efx_rc_t, rc);
781 __checkReturn efx_rc_t
785 __in uint32_t offset,
786 __out_bcount(size) caddr_t data,
791 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
792 MC_CMD_NVRAM_READ_OUT_LENMAX)];
795 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
800 (void) memset(payload, 0, sizeof (payload));
801 req.emr_cmd = MC_CMD_NVRAM_READ;
802 req.emr_in_buf = payload;
803 req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
804 req.emr_out_buf = payload;
805 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
807 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
808 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
809 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
810 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
812 efx_mcdi_execute(enp, &req);
814 if (req.emr_rc != 0) {
819 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
825 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
833 EFSYS_PROBE1(fail1, efx_rc_t, rc);
838 __checkReturn efx_rc_t
839 efx_mcdi_nvram_erase(
842 __in uint32_t offset,
846 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
847 MC_CMD_NVRAM_ERASE_OUT_LEN)];
850 (void) memset(payload, 0, sizeof (payload));
851 req.emr_cmd = MC_CMD_NVRAM_ERASE;
852 req.emr_in_buf = payload;
853 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
854 req.emr_out_buf = payload;
855 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
857 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
858 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
859 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
861 efx_mcdi_execute(enp, &req);
863 if (req.emr_rc != 0) {
871 EFSYS_PROBE1(fail1, efx_rc_t, rc);
877 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
878 * Sienna and EF10 based boards. However EF10 based boards support the use
879 * of this command with payloads up to the maximum MCDI V2 payload length.
881 __checkReturn efx_rc_t
882 efx_mcdi_nvram_write(
885 __in uint32_t offset,
886 __out_bcount(size) caddr_t data,
890 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1,
891 MCDI_CTL_SDU_LEN_MAX_V2)];
893 size_t max_data_size;
895 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length
896 - MC_CMD_NVRAM_WRITE_IN_LEN(0);
897 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0);
898 EFSYS_ASSERT3U(max_data_size, <,
899 enp->en_nic_cfg.enc_mcdi_max_payload_length);
901 if (size > max_data_size) {
906 (void) memset(payload, 0, sizeof (payload));
907 req.emr_cmd = MC_CMD_NVRAM_WRITE;
908 req.emr_in_buf = payload;
909 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
910 req.emr_out_buf = payload;
911 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
913 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
914 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
915 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
917 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
920 efx_mcdi_execute(enp, &req);
922 if (req.emr_rc != 0) {
932 EFSYS_PROBE1(fail1, efx_rc_t, rc);
939 * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
940 * NVRAM updates. Older firmware will ignore the flags field in the request.
942 __checkReturn efx_rc_t
943 efx_mcdi_nvram_update_finish(
946 __in boolean_t reboot,
947 __out_opt uint32_t *verify_resultp)
949 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
951 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
952 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)];
953 uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
956 (void) memset(payload, 0, sizeof (payload));
957 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
958 req.emr_in_buf = payload;
959 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
960 req.emr_out_buf = payload;
961 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
963 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
964 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
966 MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
967 NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
969 efx_mcdi_execute(enp, &req);
971 if (req.emr_rc != 0) {
976 if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
977 verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
978 if (encp->enc_nvram_update_verify_result_supported) {
979 /* Result of update verification is missing */
985 MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
988 if ((encp->enc_nvram_update_verify_result_supported) &&
989 (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) {
990 /* Update verification failed */
995 if (verify_resultp != NULL)
996 *verify_resultp = verify_result;
1005 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1007 /* Always report verification result */
1008 if (verify_resultp != NULL)
1009 *verify_resultp = verify_result;
1016 __checkReturn efx_rc_t
1017 efx_mcdi_nvram_test(
1018 __in efx_nic_t *enp,
1019 __in uint32_t partn)
1022 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
1023 MC_CMD_NVRAM_TEST_OUT_LEN)];
1027 (void) memset(payload, 0, sizeof (payload));
1028 req.emr_cmd = MC_CMD_NVRAM_TEST;
1029 req.emr_in_buf = payload;
1030 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
1031 req.emr_out_buf = payload;
1032 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
1034 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
1036 efx_mcdi_execute(enp, &req);
1038 if (req.emr_rc != 0) {
1043 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
1048 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
1049 if (result == MC_CMD_NVRAM_TEST_FAIL) {
1051 EFSYS_PROBE1(nvram_test_failure, int, partn);
1064 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1069 #endif /* EFSYS_OPT_DIAG */
1072 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */