diff options
author | Andrew Rybchenko <arybchik@FreeBSD.org> | 2016-12-29 08:28:42 +0000 |
---|---|---|
committer | Andrew Rybchenko <arybchik@FreeBSD.org> | 2016-12-29 08:28:42 +0000 |
commit | e9c123a567874d52ed0ce675a3281f32a24c79d4 (patch) | |
tree | 327044db06c6df57a58fb983401c8db034dedd91 /sys/dev/sfxge/common/efx_nvram.c | |
parent | 4af6e4df7c5651187ed802b3ef1398261527c330 (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.c | 90 |
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); } |