Date: Thu, 29 Dec 2016 08:28:43 +0000 (UTC) From: Andrew Rybchenko <arybchik@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r310765 - head/sys/dev/sfxge/common Message-ID: <201612290828.uBT8Shd6088578@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: arybchik Date: Thu Dec 29 08:28:42 2016 New Revision: 310765 URL: https://svnweb.freebsd.org/changeset/base/310765 Log: 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 Modified: head/sys/dev/sfxge/common/ef10_impl.h head/sys/dev/sfxge/common/ef10_nic.c head/sys/dev/sfxge/common/ef10_nvram.c head/sys/dev/sfxge/common/efx.h head/sys/dev/sfxge/common/efx_impl.h head/sys/dev/sfxge/common/efx_nvram.c head/sys/dev/sfxge/common/siena_impl.h head/sys/dev/sfxge/common/siena_nic.c head/sys/dev/sfxge/common/siena_nvram.c Modified: head/sys/dev/sfxge/common/ef10_impl.h ============================================================================== --- head/sys/dev/sfxge/common/ef10_impl.h Thu Dec 29 08:25:00 2016 (r310764) +++ head/sys/dev/sfxge/common/ef10_impl.h Thu Dec 29 08:28:42 2016 (r310765) @@ -384,7 +384,7 @@ ef10_nvram_partn_lock( __in efx_nic_t *enp, __in uint32_t partn); -extern void +extern __checkReturn efx_rc_t ef10_nvram_partn_unlock( __in efx_nic_t *enp, __in uint32_t partn); @@ -451,7 +451,7 @@ ef10_nvram_partn_write( __out_bcount(size) caddr_t data, __in size_t size); -extern void +extern __checkReturn efx_rc_t ef10_nvram_partn_rw_finish( __in efx_nic_t *enp, __in uint32_t partn); Modified: head/sys/dev/sfxge/common/ef10_nic.c ============================================================================== --- head/sys/dev/sfxge/common/ef10_nic.c Thu Dec 29 08:25:00 2016 (r310764) +++ head/sys/dev/sfxge/common/ef10_nic.c Thu Dec 29 08:28:42 2016 (r310765) @@ -1105,6 +1105,18 @@ ef10_get_datapath_caps( encp->enc_mac_stats_40g_tx_size_bins = CAP_FLAG2(flags2, MAC_STATS_40G_TX_SIZE_BINS) ? B_TRUE : B_FALSE; + /* + * Check if firmware-verified NVRAM updates must be used. + * + * The firmware trusted installer requires all NVRAM updates to use + * version 2 of MC_CMD_NVRAM_UPDATE_START (to enable verified update) + * and version 2 of MC_CMD_NVRAM_UPDATE_FINISH (to verify the updated + * partition and report the result). + */ + encp->enc_fw_verified_nvram_update_required = + CAP_FLAG2(flags2, NVRAM_UPDATE_REPORT_VERIFY_RESULT) ? + B_TRUE : B_FALSE; + #undef CAP_FLAG #undef CAP_FLAG2 Modified: head/sys/dev/sfxge/common/ef10_nvram.c ============================================================================== --- head/sys/dev/sfxge/common/ef10_nvram.c Thu Dec 29 08:25:00 2016 (r310764) +++ head/sys/dev/sfxge/common/ef10_nvram.c Thu Dec 29 08:28:42 2016 (r310765) @@ -2046,22 +2046,26 @@ fail1: return (rc); } - void + __checkReturn efx_rc_t ef10_nvram_partn_unlock( __in efx_nic_t *enp, __in uint32_t partn) { - boolean_t reboot; + boolean_t reboot = B_FALSE; + uint32_t result = 0; /* FIXME: MC_CMD_NVRAM_VERIFY_RC_UNKNOWN */ efx_rc_t rc; - reboot = B_FALSE; - if ((rc = efx_mcdi_nvram_update_finish(enp, partn, reboot)) != 0) + rc = efx_mcdi_nvram_update_finish(enp, partn, reboot, &result); + if (rc != 0) goto fail1; - return; + return (0); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); + + /* FIXME: log result if verified firmware update fails */ + return (rc); } __checkReturn efx_rc_t @@ -2359,12 +2363,22 @@ fail1: return (rc); } - void + __checkReturn efx_rc_t ef10_nvram_partn_rw_finish( __in efx_nic_t *enp, __in uint32_t partn) { - ef10_nvram_partn_unlock(enp, partn); + efx_rc_t rc; + + if ((rc = ef10_nvram_partn_unlock(enp, partn)) != 0) + goto fail1; + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); } #endif /* EFSYS_OPT_NVRAM */ Modified: head/sys/dev/sfxge/common/efx.h ============================================================================== --- head/sys/dev/sfxge/common/efx.h Thu Dec 29 08:25:00 2016 (r310764) +++ head/sys/dev/sfxge/common/efx.h Thu Dec 29 08:28:42 2016 (r310765) @@ -1183,6 +1183,8 @@ typedef struct efx_nic_cfg_s { /* Minimum unidirectional bandwidth in Mb/s to max out all ports */ uint32_t enc_required_pcie_bandwidth_mbps; uint32_t enc_max_pcie_link_gen; + /* Firmware verifies integrity of NVRAM updates */ + uint32_t enc_fw_verified_nvram_update_required; } efx_nic_cfg_t; #define EFX_PCI_FUNCTION_IS_PF(_encp) ((_encp)->enc_vf == 0xffff) @@ -1366,7 +1368,7 @@ efx_nvram_rw_start( __in efx_nvram_type_t type, __out_opt size_t *pref_chunkp); -extern void +extern __checkReturn efx_rc_t efx_nvram_rw_finish( __in efx_nic_t *enp, __in efx_nvram_type_t type); Modified: head/sys/dev/sfxge/common/efx_impl.h ============================================================================== --- head/sys/dev/sfxge/common/efx_impl.h Thu Dec 29 08:25:00 2016 (r310764) +++ head/sys/dev/sfxge/common/efx_impl.h Thu Dec 29 08:28:42 2016 (r310765) @@ -453,7 +453,7 @@ typedef struct efx_nvram_ops_s { unsigned int, size_t); efx_rc_t (*envo_partn_write)(efx_nic_t *, uint32_t, unsigned int, caddr_t, size_t); - void (*envo_partn_rw_finish)(efx_nic_t *, uint32_t); + efx_rc_t (*envo_partn_rw_finish)(efx_nic_t *, uint32_t); efx_rc_t (*envo_partn_get_version)(efx_nic_t *, uint32_t, uint32_t *, uint16_t *); efx_rc_t (*envo_partn_set_version)(efx_nic_t *, uint32_t, @@ -541,7 +541,8 @@ efx_mcdi_nvram_write( 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); #if EFSYS_OPT_DIAG Modified: head/sys/dev/sfxge/common/efx_nvram.c ============================================================================== --- head/sys/dev/sfxge/common/efx_nvram.c Thu Dec 29 08:25:00 2016 (r310764) +++ head/sys/dev/sfxge/common/efx_nvram.c Thu Dec 29 08:28:42 2016 (r310765) @@ -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); } Modified: head/sys/dev/sfxge/common/siena_impl.h ============================================================================== --- head/sys/dev/sfxge/common/siena_impl.h Thu Dec 29 08:25:00 2016 (r310764) +++ head/sys/dev/sfxge/common/siena_impl.h Thu Dec 29 08:28:42 2016 (r310765) @@ -136,7 +136,7 @@ siena_nvram_partn_lock( __in efx_nic_t *enp, __in uint32_t partn); -extern void +extern __checkReturn efx_rc_t siena_nvram_partn_unlock( __in efx_nic_t *enp, __in uint32_t partn); @@ -208,7 +208,7 @@ siena_nvram_partn_write( __out_bcount(size) caddr_t data, __in size_t size); -extern void +extern __checkReturn efx_rc_t siena_nvram_partn_rw_finish( __in efx_nic_t *enp, __in uint32_t partn); Modified: head/sys/dev/sfxge/common/siena_nic.c ============================================================================== --- head/sys/dev/sfxge/common/siena_nic.c Thu Dec 29 08:25:00 2016 (r310764) +++ head/sys/dev/sfxge/common/siena_nic.c Thu Dec 29 08:28:42 2016 (r310765) @@ -166,6 +166,8 @@ siena_board_cfg( encp->enc_required_pcie_bandwidth_mbps = 2 * 10000; encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2; + encp->enc_fw_verified_nvram_update_required = B_FALSE; + return (0); fail2: Modified: head/sys/dev/sfxge/common/siena_nvram.c ============================================================================== --- head/sys/dev/sfxge/common/siena_nvram.c Thu Dec 29 08:25:00 2016 (r310764) +++ head/sys/dev/sfxge/common/siena_nvram.c Thu Dec 29 08:28:42 2016 (r310765) @@ -170,7 +170,7 @@ fail1: return (rc); } - void + __checkReturn efx_rc_t siena_nvram_partn_unlock( __in efx_nic_t *enp, __in uint32_t partn) @@ -186,14 +186,16 @@ siena_nvram_partn_unlock( partn == MC_CMD_NVRAM_TYPE_PHY_PORT1 || partn == MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO); - if ((rc = efx_mcdi_nvram_update_finish(enp, partn, reboot)) != 0) { + rc = efx_mcdi_nvram_update_finish(enp, partn, reboot, NULL); + if (rc != 0) goto fail1; - } - return; + return (0); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); } #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */ @@ -585,12 +587,22 @@ fail1: return (rc); } - void + __checkReturn efx_rc_t siena_nvram_partn_rw_finish( __in efx_nic_t *enp, __in uint32_t partn) { - siena_nvram_partn_unlock(enp, partn); + efx_rc_t rc; + + if ((rc = siena_nvram_partn_unlock(enp, partn)) != 0) + goto fail1; + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); } __checkReturn efx_rc_t
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612290828.uBT8Shd6088578>