aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/sfxge/common/efx_nvram.c
diff options
context:
space:
mode:
authorAndrew Rybchenko <arybchik@FreeBSD.org>2016-12-29 08:28:42 +0000
committerAndrew Rybchenko <arybchik@FreeBSD.org>2016-12-29 08:28:42 +0000
commite9c123a567874d52ed0ce675a3281f32a24c79d4 (patch)
tree327044db06c6df57a58fb983401c8db034dedd91 /sys/dev/sfxge/common/efx_nvram.c
parent4af6e4df7c5651187ed802b3ef1398261527c330 (diff)
sfxge(4): add support for firmware-verified NVRAM updates to the common code
Submitted by: Andy Moreton <amoreton at solarflare.com> Reviewed by: gnn Sponsored by: Solarflare Communications, Inc. MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D8942
Notes
Notes: svn path=/head/; revision=310765
Diffstat (limited to 'sys/dev/sfxge/common/efx_nvram.c')
-rw-r--r--sys/dev/sfxge/common/efx_nvram.c90
1 files changed, 77 insertions, 13 deletions
diff --git a/sys/dev/sfxge/common/efx_nvram.c b/sys/dev/sfxge/common/efx_nvram.c
index a17cd789f487..60169fc31cdf 100644
--- a/sys/dev/sfxge/common/efx_nvram.c
+++ b/sys/dev/sfxge/common/efx_nvram.c
@@ -362,13 +362,14 @@ fail1:
return (rc);
}
- void
+ __checkReturn efx_rc_t
efx_nvram_rw_finish(
__in efx_nic_t *enp,
__in efx_nvram_type_t type)
{
const efx_nvram_ops_t *envop = enp->en_envop;
uint32_t partn;
+ efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
@@ -378,10 +379,24 @@ efx_nvram_rw_finish(
EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
- if (envop->envo_type_to_partn(enp, type, &partn) == 0)
- envop->envo_partn_rw_finish(enp, partn);
+ if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
+ goto fail1;
+
+ if ((rc = envop->envo_partn_rw_finish(enp, partn)) != 0)
+ goto fail2;
+
+ enp->en_nvram_locked = EFX_NVRAM_INVALID;
+
+ return (0);
+fail2:
+ EFSYS_PROBE(fail2);
enp->en_nvram_locked = EFX_NVRAM_INVALID;
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
}
__checkReturn efx_rc_t
@@ -696,12 +711,16 @@ fail1:
return (rc);
}
+/*
+ * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
+ * NVRAM updates. Older firmware will ignore the flags field in the request.
+ */
__checkReturn efx_rc_t
efx_mcdi_nvram_update_start(
__in efx_nic_t *enp,
__in uint32_t partn)
{
- uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_IN_LEN,
+ uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
efx_mcdi_req_t req;
efx_rc_t rc;
@@ -709,11 +728,14 @@ efx_mcdi_nvram_update_start(
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
req.emr_in_buf = payload;
- req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN;
+ req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
req.emr_out_buf = payload;
req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
- MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn);
+ MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
+
+ MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
+ NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
efx_mcdi_execute(enp, &req);
@@ -886,26 +908,37 @@ fail1:
return (rc);
}
+
+/*
+ * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
+ * NVRAM updates. Older firmware will ignore the flags field in the request.
+ */
__checkReturn efx_rc_t
efx_mcdi_nvram_update_finish(
__in efx_nic_t *enp,
__in uint32_t partn,
- __in boolean_t reboot)
+ __in boolean_t reboot,
+ __out_opt uint32_t *resultp)
{
+ const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN,
- MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN)];
+ uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
+ MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)];
+ uint32_t result = 0; /* FIXME: use MC_CMD_NVRAM_VERIFY_RC_UNKNOWN */
efx_rc_t rc;
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
req.emr_in_buf = payload;
- req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN;
+ req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
req.emr_out_buf = payload;
- req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN;
+ req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
- MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn);
- MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot);
+ MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
+ MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
+
+ MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
+ NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
efx_mcdi_execute(enp, &req);
@@ -914,11 +947,42 @@ efx_mcdi_nvram_update_finish(
goto fail1;
}
+ if (encp->enc_fw_verified_nvram_update_required == B_FALSE) {
+ /* Report success if verified updates are not supported. */
+ result = MC_CMD_NVRAM_VERIFY_RC_SUCCESS;
+ } else {
+ /* Firmware-verified NVRAM updates are required */
+ if (req.emr_out_length_used <
+ MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+ result =
+ MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
+
+ if (result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) {
+ /* Mandatory verification failed */
+ rc = EINVAL;
+ goto fail3;
+ }
+ }
+
+ if (resultp != NULL)
+ *resultp = result;
+
return (0);
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ /* Always report verification result */
+ if (resultp != NULL)
+ *resultp = result;
+
return (rc);
}