efx_lic.c revision 342445
1247835Skib/*- 2247835Skib * Copyright (c) 2009-2016 Solarflare Communications Inc. 3247835Skib * All rights reserved. 4247835Skib * 5247835Skib * Redistribution and use in source and binary forms, with or without 6247835Skib * modification, are permitted provided that the following conditions are met: 7247835Skib * 8247835Skib * 1. Redistributions of source code must retain the above copyright notice, 9247835Skib * this list of conditions and the following disclaimer. 10247835Skib * 2. Redistributions in binary form must reproduce the above copyright notice, 11247835Skib * this list of conditions and the following disclaimer in the documentation 12247835Skib * and/or other materials provided with the distribution. 13247835Skib * 14247835Skib * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15247835Skib * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16247835Skib * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17247835Skib * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18247835Skib * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19247835Skib * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20247835Skib * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21247835Skib * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22247835Skib * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23247835Skib * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24247835Skib * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25247835Skib * 26247835Skib * The views and conclusions contained in the software and documentation are 27247835Skib * those of the authors and should not be interpreted as representing official 28247835Skib * policies, either expressed or implied, of the FreeBSD Project. 29247835Skib */ 30247835Skib 31247835Skib#include <sys/cdefs.h> 32247835Skib__FBSDID("$FreeBSD: stable/11/sys/dev/sfxge/common/efx_lic.c 342445 2018-12-25 07:27:45Z arybchik $"); 33247835Skib 34247835Skib#include "efx.h" 35247835Skib#include "efx_impl.h" 36247835Skib 37247835Skib#if EFSYS_OPT_LICENSING 38247835Skib 39247835Skib#include "ef10_tlv_layout.h" 40247835Skib 41247835Skib#if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON 42247835Skib 43247835Skib __checkReturn efx_rc_t 44247835Skibefx_lic_v1v2_find_start( 45247835Skib __in efx_nic_t *enp, 46247835Skib __in_bcount(buffer_size) 47247835Skib caddr_t bufferp, 48247835Skib __in size_t buffer_size, 49247835Skib __out uint32_t *startp 50247835Skib ); 51247835Skib 52247835Skib __checkReturn efx_rc_t 53247835Skibefx_lic_v1v2_find_end( 54247835Skib __in efx_nic_t *enp, 55247835Skib __in_bcount(buffer_size) 56247835Skib caddr_t bufferp, 57247835Skib __in size_t buffer_size, 58247835Skib __in uint32_t offset, 59247835Skib __out uint32_t *endp 60247835Skib ); 61247835Skib 62247835Skib __checkReturn __success(return != B_FALSE) boolean_t 63247835Skibefx_lic_v1v2_find_key( 64247835Skib __in efx_nic_t *enp, 65247835Skib __in_bcount(buffer_size) 66247835Skib caddr_t bufferp, 67247835Skib __in size_t buffer_size, 68247835Skib __in uint32_t offset, 69247835Skib __out uint32_t *startp, 70247835Skib __out uint32_t *lengthp 71247835Skib ); 72247835Skib 73247835Skib __checkReturn __success(return != B_FALSE) boolean_t 74247835Skibefx_lic_v1v2_validate_key( 75247835Skib __in efx_nic_t *enp, 76247835Skib __in_bcount(length) caddr_t keyp, 77247835Skib __in uint32_t length 78247835Skib ); 79247835Skib 80247835Skib __checkReturn efx_rc_t 81247835Skibefx_lic_v1v2_read_key( 82247835Skib __in efx_nic_t *enp, 83247835Skib __in_bcount(buffer_size) 84247835Skib caddr_t bufferp, 85247835Skib __in size_t buffer_size, 86247835Skib __in uint32_t offset, 87247835Skib __in uint32_t length, 88247835Skib __out_bcount_part(key_max_size, *lengthp) 89247835Skib caddr_t keyp, 90247835Skib __in size_t key_max_size, 91247835Skib __out uint32_t *lengthp 92247835Skib ); 93247835Skib 94247835Skib __checkReturn efx_rc_t 95247835Skibefx_lic_v1v2_write_key( 96247835Skib __in efx_nic_t *enp, 97247835Skib __in_bcount(buffer_size) 98247835Skib caddr_t bufferp, 99247835Skib __in size_t buffer_size, 100247835Skib __in uint32_t offset, 101247835Skib __in_bcount(length) caddr_t keyp, 102247835Skib __in uint32_t length, 103247835Skib __out uint32_t *lengthp 104247835Skib ); 105247835Skib 106247835Skib __checkReturn efx_rc_t 107247835Skibefx_lic_v1v2_delete_key( 108247835Skib __in efx_nic_t *enp, 109247835Skib __in_bcount(buffer_size) 110247849Skib caddr_t bufferp, 111247849Skib __in size_t buffer_size, 112247849Skib __in uint32_t offset, 113247849Skib __in uint32_t length, 114247849Skib __in uint32_t end, 115247849Skib __out uint32_t *deltap 116247849Skib ); 117247849Skib 118247835Skib __checkReturn efx_rc_t 119247835Skibefx_lic_v1v2_create_partition( 120247849Skib __in efx_nic_t *enp, 121247849Skib __in_bcount(buffer_size) 122247849Skib caddr_t bufferp, 123247849Skib __in size_t buffer_size 124247849Skib ); 125247849Skib 126247835Skib __checkReturn efx_rc_t 127247835Skibefx_lic_v1v2_finish_partition( 128247835Skib __in efx_nic_t *enp, 129247835Skib __in_bcount(buffer_size) 130247835Skib caddr_t bufferp, 131247835Skib __in size_t buffer_size 132247835Skib ); 133247835Skib 134247835Skib#endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */ 135247835Skib 136247835Skib 137247835Skib#if EFSYS_OPT_SIENA 138267548Sattilio 139247835Skibstatic __checkReturn efx_rc_t 140247835Skibefx_mcdi_fc_license_update_license( 141247835Skib __in efx_nic_t *enp); 142247835Skib 143247835Skibstatic __checkReturn efx_rc_t 144247835Skibefx_mcdi_fc_license_get_key_stats( 145247835Skib __in efx_nic_t *enp, 146247835Skib __out efx_key_stats_t *eksp); 147247835Skib 148247835Skibstatic const efx_lic_ops_t __efx_lic_v1_ops = { 149247835Skib efx_mcdi_fc_license_update_license, /* elo_update_licenses */ 150247835Skib efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */ 151247835Skib NULL, /* elo_app_state */ 152247835Skib NULL, /* elo_get_id */ 153247835Skib efx_lic_v1v2_find_start, /* elo_find_start */ 154247835Skib efx_lic_v1v2_find_end, /* elo_find_end */ 155247835Skib efx_lic_v1v2_find_key, /* elo_find_key */ 156247835Skib efx_lic_v1v2_validate_key, /* elo_validate_key */ 157247835Skib efx_lic_v1v2_read_key, /* elo_read_key */ 158247835Skib efx_lic_v1v2_write_key, /* elo_write_key */ 159247835Skib efx_lic_v1v2_delete_key, /* elo_delete_key */ 160247835Skib efx_lic_v1v2_create_partition, /* elo_create_partition */ 161247835Skib efx_lic_v1v2_finish_partition, /* elo_finish_partition */ 162247835Skib}; 163247835Skib 164247835Skib#endif /* EFSYS_OPT_SIENA */ 165247835Skib 166247835Skib#if EFSYS_OPT_HUNTINGTON 167247835Skib 168247835Skibstatic __checkReturn efx_rc_t 169247835Skibefx_mcdi_licensing_update_licenses( 170247835Skib __in efx_nic_t *enp); 171247835Skib 172247835Skibstatic __checkReturn efx_rc_t 173247835Skibefx_mcdi_licensing_get_key_stats( 174247835Skib __in efx_nic_t *enp, 175247835Skib __out efx_key_stats_t *eksp); 176247835Skib 177247835Skibstatic __checkReturn efx_rc_t 178247835Skibefx_mcdi_licensed_app_state( 179247835Skib __in efx_nic_t *enp, 180247835Skib __in uint64_t app_id, 181247835Skib __out boolean_t *licensedp); 182247835Skib 183247835Skibstatic const efx_lic_ops_t __efx_lic_v2_ops = { 184247835Skib efx_mcdi_licensing_update_licenses, /* elo_update_licenses */ 185247835Skib efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */ 186247835Skib efx_mcdi_licensed_app_state, /* elo_app_state */ 187247835Skib NULL, /* elo_get_id */ 188247835Skib efx_lic_v1v2_find_start, /* elo_find_start */ 189247835Skib efx_lic_v1v2_find_end, /* elo_find_end */ 190247835Skib efx_lic_v1v2_find_key, /* elo_find_key */ 191247835Skib efx_lic_v1v2_validate_key, /* elo_validate_key */ 192247835Skib efx_lic_v1v2_read_key, /* elo_read_key */ 193247835Skib efx_lic_v1v2_write_key, /* elo_write_key */ 194247835Skib efx_lic_v1v2_delete_key, /* elo_delete_key */ 195247835Skib efx_lic_v1v2_create_partition, /* elo_create_partition */ 196247835Skib efx_lic_v1v2_finish_partition, /* elo_finish_partition */ 197247835Skib}; 198247835Skib 199247835Skib#endif /* EFSYS_OPT_HUNTINGTON */ 200247835Skib 201247835Skib#if EFSYS_OPT_MEDFORD 202247835Skib 203247835Skibstatic __checkReturn efx_rc_t 204247835Skibefx_mcdi_licensing_v3_update_licenses( 205247835Skib __in efx_nic_t *enp); 206247835Skib 207247835Skibstatic __checkReturn efx_rc_t 208247835Skibefx_mcdi_licensing_v3_report_license( 209247835Skib __in efx_nic_t *enp, 210247835Skib __out efx_key_stats_t *eksp); 211247835Skib 212247835Skibstatic __checkReturn efx_rc_t 213247835Skibefx_mcdi_licensing_v3_app_state( 214247835Skib __in efx_nic_t *enp, 215247835Skib __in uint64_t app_id, 216247835Skib __out boolean_t *licensedp); 217247835Skib 218247835Skibstatic __checkReturn efx_rc_t 219273862Stijlefx_mcdi_licensing_v3_get_id( 220247835Skib __in efx_nic_t *enp, 221247835Skib __in size_t buffer_size, 222273862Stijl __out uint32_t *typep, 223273862Stijl __out size_t *lengthp, 224247835Skib __out_bcount_part_opt(buffer_size, *lengthp) 225247835Skib uint8_t *bufferp); 226247835Skib 227247835Skib __checkReturn efx_rc_t 228247835Skibefx_lic_v3_find_start( 229247835Skib __in efx_nic_t *enp, 230273862Stijl __in_bcount(buffer_size) 231247835Skib caddr_t bufferp, 232247835Skib __in size_t buffer_size, 233273862Stijl __out uint32_t *startp 234273862Stijl ); 235247835Skib 236247835Skib __checkReturn efx_rc_t 237247835Skibefx_lic_v3_find_end( 238247835Skib __in efx_nic_t *enp, 239247835Skib __in_bcount(buffer_size) 240247835Skib caddr_t bufferp, 241273862Stijl __in size_t buffer_size, 242247835Skib __in uint32_t offset, 243247835Skib __out uint32_t *endp 244273862Stijl ); 245273862Stijl 246247835Skib __checkReturn __success(return != B_FALSE) boolean_t 247247835Skibefx_lic_v3_find_key( 248247835Skib __in efx_nic_t *enp, 249247835Skib __in_bcount(buffer_size) 250247835Skib caddr_t bufferp, 251247835Skib __in size_t buffer_size, 252247835Skib __in uint32_t offset, 253247835Skib __out uint32_t *startp, 254247835Skib __out uint32_t *lengthp 255247835Skib ); 256247835Skib 257247835Skib __checkReturn __success(return != B_FALSE) boolean_t 258247835Skibefx_lic_v3_validate_key( 259247835Skib __in efx_nic_t *enp, 260247835Skib __in_bcount(length) caddr_t keyp, 261247835Skib __in uint32_t length 262247835Skib ); 263247835Skib 264247835Skib __checkReturn efx_rc_t 265247835Skibefx_lic_v3_read_key( 266247835Skib __in efx_nic_t *enp, 267247835Skib __in_bcount(buffer_size) 268247835Skib caddr_t bufferp, 269247835Skib __in size_t buffer_size, 270247835Skib __in uint32_t offset, 271247835Skib __in uint32_t length, 272247835Skib __out_bcount_part(key_max_size, *lengthp) 273247835Skib caddr_t keyp, 274247835Skib __in size_t key_max_size, 275247835Skib __out uint32_t *lengthp 276247835Skib ); 277247835Skib 278247835Skib __checkReturn efx_rc_t 279247835Skibefx_lic_v3_write_key( 280247835Skib __in efx_nic_t *enp, 281247835Skib __in_bcount(buffer_size) 282247835Skib caddr_t bufferp, 283247835Skib __in size_t buffer_size, 284247835Skib __in uint32_t offset, 285247835Skib __in_bcount(length) caddr_t keyp, 286247835Skib __in uint32_t length, 287247835Skib __out uint32_t *lengthp 288247835Skib ); 289247835Skib 290247835Skib __checkReturn efx_rc_t 291247835Skibefx_lic_v3_delete_key( 292247835Skib __in efx_nic_t *enp, 293247835Skib __in_bcount(buffer_size) 294247835Skib caddr_t bufferp, 295247835Skib __in size_t buffer_size, 296247835Skib __in uint32_t offset, 297247835Skib __in uint32_t length, 298247835Skib __in uint32_t end, 299247835Skib __out uint32_t *deltap 300247835Skib ); 301247835Skib 302247835Skib __checkReturn efx_rc_t 303247835Skibefx_lic_v3_create_partition( 304247835Skib __in efx_nic_t *enp, 305254873Sdumbbell __in_bcount(buffer_size) 306247835Skib caddr_t bufferp, 307247835Skib __in size_t buffer_size 308247835Skib ); 309247835Skib 310247835Skib __checkReturn efx_rc_t 311247835Skibefx_lic_v3_finish_partition( 312247835Skib __in efx_nic_t *enp, 313247835Skib __in_bcount(buffer_size) 314247835Skib caddr_t bufferp, 315247835Skib __in size_t buffer_size 316254182Skib ); 317247835Skib 318247835Skibstatic const efx_lic_ops_t __efx_lic_v3_ops = { 319247835Skib efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */ 320247835Skib efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */ 321247835Skib efx_mcdi_licensing_v3_app_state, /* elo_app_state */ 322247835Skib efx_mcdi_licensing_v3_get_id, /* elo_get_id */ 323247835Skib efx_lic_v3_find_start, /* elo_find_start*/ 324254873Sdumbbell efx_lic_v3_find_end, /* elo_find_end */ 325254873Sdumbbell efx_lic_v3_find_key, /* elo_find_key */ 326247835Skib efx_lic_v3_validate_key, /* elo_validate_key */ 327247835Skib efx_lic_v3_read_key, /* elo_read_key */ 328247835Skib efx_lic_v3_write_key, /* elo_write_key */ 329247835Skib efx_lic_v3_delete_key, /* elo_delete_key */ 330247835Skib efx_lic_v3_create_partition, /* elo_create_partition */ 331247835Skib efx_lic_v3_finish_partition, /* elo_finish_partition */ 332247835Skib}; 333247835Skib 334247835Skib#endif /* EFSYS_OPT_MEDFORD */ 335247835Skib 336247835Skib 337247835Skib/* V1 Licensing - used in Siena Modena only */ 338247835Skib 339247835Skib#if EFSYS_OPT_SIENA 340247835Skib 341247835Skibstatic __checkReturn efx_rc_t 342247835Skibefx_mcdi_fc_license_update_license( 343247835Skib __in efx_nic_t *enp) 344247835Skib{ 345247835Skib efx_mcdi_req_t req; 346247835Skib EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN, 0); 347247835Skib efx_rc_t rc; 348247835Skib 349247835Skib EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 350247835Skib 351247835Skib req.emr_cmd = MC_CMD_FC; 352247835Skib req.emr_in_buf = payload; 353247835Skib req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN; 354247835Skib req.emr_out_buf = payload; 355247835Skib req.emr_out_length = 0; 356247835Skib 357247835Skib MCDI_IN_SET_DWORD(req, FC_IN_CMD, 358247835Skib MC_CMD_FC_OP_LICENSE); 359247835Skib 360254873Sdumbbell MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP, 361254873Sdumbbell MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE); 362247835Skib 363247835Skib efx_mcdi_execute(enp, &req); 364247835Skib 365247835Skib if (req.emr_rc != 0) { 366247835Skib rc = req.emr_rc; 367247835Skib goto fail1; 368247835Skib } 369247835Skib 370247835Skib if (req.emr_out_length_used != 0) { 371247835Skib rc = EIO; 372247835Skib goto fail2; 373247835Skib } 374247835Skib 375247835Skib return (0); 376247835Skib 377247835Skibfail2: 378247835Skib EFSYS_PROBE(fail2); 379247835Skibfail1: 380247835Skib EFSYS_PROBE1(fail1, efx_rc_t, rc); 381247835Skib 382247835Skib return (rc); 383247835Skib} 384247835Skib 385247835Skibstatic __checkReturn efx_rc_t 386247835Skibefx_mcdi_fc_license_get_key_stats( 387247835Skib __in efx_nic_t *enp, 388247835Skib __out efx_key_stats_t *eksp) 389247835Skib{ 390247835Skib efx_mcdi_req_t req; 391247835Skib EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN, 392247835Skib MC_CMD_FC_OUT_LICENSE_LEN); 393247835Skib efx_rc_t rc; 394247835Skib 395247835Skib EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 396247835Skib 397247835Skib req.emr_cmd = MC_CMD_FC; 398247835Skib req.emr_in_buf = payload; 399247835Skib req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN; 400247835Skib req.emr_out_buf = payload; 401247835Skib req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN; 402247835Skib 403247835Skib MCDI_IN_SET_DWORD(req, FC_IN_CMD, 404247835Skib MC_CMD_FC_OP_LICENSE); 405247835Skib 406247835Skib MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP, 407247835Skib MC_CMD_FC_IN_LICENSE_GET_KEY_STATS); 408247835Skib 409247835Skib efx_mcdi_execute_quiet(enp, &req); 410247835Skib 411247835Skib if (req.emr_rc != 0) { 412247835Skib rc = req.emr_rc; 413247835Skib goto fail1; 414247835Skib } 415247835Skib 416247835Skib if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) { 417247835Skib rc = EMSGSIZE; 418247835Skib goto fail2; 419247835Skib } 420247835Skib 421247835Skib eksp->eks_valid = 422247835Skib MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS); 423247835Skib eksp->eks_invalid = 424247835Skib MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS); 425247835Skib eksp->eks_blacklisted = 426247835Skib MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS); 427247835Skib eksp->eks_unverifiable = 0; 428247835Skib eksp->eks_wrong_node = 0; 429247835Skib eksp->eks_licensed_apps_lo = 0; 430247835Skib eksp->eks_licensed_apps_hi = 0; 431247835Skib eksp->eks_licensed_features_lo = 0; 432247835Skib eksp->eks_licensed_features_hi = 0; 433247835Skib 434247835Skib return (0); 435247835Skib 436247835Skibfail2: 437247835Skib EFSYS_PROBE(fail2); 438247835Skibfail1: 439247835Skib EFSYS_PROBE1(fail1, efx_rc_t, rc); 440247835Skib 441247835Skib return (rc); 442247835Skib} 443247835Skib 444247835Skib#endif /* EFSYS_OPT_SIENA */ 445247835Skib 446247835Skib/* V1 and V2 Partition format - based on a 16-bit TLV format */ 447247835Skib 448247835Skib#if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON 449247835Skib 450247835Skib/* 451247835Skib * V1/V2 format - defined in SF-108542-TC section 4.2: 452247835Skib * Type (T): 16bit - revision/HMAC algorithm 453247835Skib * Length (L): 16bit - value length in bytes 454247835Skib * Value (V): L bytes - payload 455247835Skib */ 456247835Skib#define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256) 457247835Skib#define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof(uint16_t)) 458254182Skib 459247835Skib __checkReturn efx_rc_t 460247835Skibefx_lic_v1v2_find_start( 461247835Skib __in efx_nic_t *enp, 462247835Skib __in_bcount(buffer_size) 463247835Skib caddr_t bufferp, 464247835Skib __in size_t buffer_size, 465247835Skib __out uint32_t *startp 466247835Skib ) 467247835Skib{ 468247835Skib _NOTE(ARGUNUSED(enp, bufferp, buffer_size)) 469247835Skib 470247835Skib *startp = 0; 471247835Skib return (0); 472247835Skib} 473247835Skib 474247835Skib __checkReturn efx_rc_t 475247835Skibefx_lic_v1v2_find_end( 476247835Skib __in efx_nic_t *enp, 477247835Skib __in_bcount(buffer_size) 478247835Skib caddr_t bufferp, 479247835Skib __in size_t buffer_size, 480247835Skib __in uint32_t offset, 481247835Skib __out uint32_t *endp 482247835Skib ) 483247835Skib{ 484247835Skib _NOTE(ARGUNUSED(enp, bufferp, buffer_size)) 485247835Skib 486247835Skib *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH; 487247835Skib return (0); 488247835Skib} 489247835Skib 490247835Skib __checkReturn __success(return != B_FALSE) boolean_t 491247835Skibefx_lic_v1v2_find_key( 492247835Skib __in efx_nic_t *enp, 493247835Skib __in_bcount(buffer_size) 494247835Skib caddr_t bufferp, 495247835Skib __in size_t buffer_size, 496247835Skib __in uint32_t offset, 497247835Skib __out uint32_t *startp, 498247835Skib __out uint32_t *lengthp 499247835Skib ) 500247835Skib{ 501247835Skib boolean_t found; 502247835Skib uint16_t tlv_type; 503247835Skib uint16_t tlv_length; 504247835Skib 505247835Skib _NOTE(ARGUNUSED(enp)) 506247835Skib 507247835Skib if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH) 508247835Skib goto fail1; 509247835Skib 510247835Skib tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]); 511247835Skib tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]); 512247835Skib if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) || 513247835Skib (tlv_type == 0 && tlv_length == 0)) { 514247835Skib found = B_FALSE; 515247835Skib } else { 516247835Skib *startp = offset; 517247835Skib *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH; 518247835Skib found = B_TRUE; 519247835Skib } 520247835Skib return (found); 521247835Skib 522247835Skibfail1: 523247835Skib EFSYS_PROBE1(fail1, boolean_t, B_FALSE); 524247835Skib 525247835Skib return (B_FALSE); 526247835Skib} 527247835Skib 528247835Skib __checkReturn __success(return != B_FALSE) boolean_t 529247835Skibefx_lic_v1v2_validate_key( 530247835Skib __in efx_nic_t *enp, 531247835Skib __in_bcount(length) caddr_t keyp, 532247835Skib __in uint32_t length 533254182Skib ) 534247835Skib{ 535247835Skib uint16_t tlv_type; 536247835Skib uint16_t tlv_length; 537247835Skib 538247835Skib _NOTE(ARGUNUSED(enp)) 539247835Skib 540247835Skib if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) { 541247835Skib goto fail1; 542247835Skib } 543247835Skib 544247835Skib tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]); 545247835Skib tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]); 546247835Skib 547247835Skib if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) { 548247835Skib goto fail2; 549247835Skib } 550247835Skib if (tlv_type == 0) { 551247835Skib goto fail3; 552247835Skib } 553247835Skib if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) { 554247835Skib goto fail4; 555247835Skib } 556247835Skib 557247835Skib return (B_TRUE); 558247835Skib 559247835Skibfail4: 560247835Skib EFSYS_PROBE(fail4); 561247835Skibfail3: 562247835Skib EFSYS_PROBE(fail3); 563247835Skibfail2: 564247835Skib EFSYS_PROBE(fail2); 565247835Skibfail1: 566247835Skib EFSYS_PROBE1(fail1, boolean_t, B_FALSE); 567247835Skib 568247835Skib return (B_FALSE); 569247835Skib} 570247835Skib 571247835Skib 572247835Skib __checkReturn efx_rc_t 573247835Skibefx_lic_v1v2_read_key( 574247835Skib __in efx_nic_t *enp, 575247835Skib __in_bcount(buffer_size) 576247835Skib caddr_t bufferp, 577247835Skib __in size_t buffer_size, 578247835Skib __in uint32_t offset, 579247835Skib __in uint32_t length, 580247835Skib __out_bcount_part(key_max_size, *lengthp) 581247835Skib caddr_t keyp, 582247835Skib __in size_t key_max_size, 583247835Skib __out uint32_t *lengthp 584247835Skib ) 585247835Skib{ 586247835Skib efx_rc_t rc; 587247835Skib 588254182Skib _NOTE(ARGUNUSED(enp, buffer_size)) 589247835Skib EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX + 590247835Skib EFX_LICENSE_V1V2_HEADER_LENGTH)); 591247835Skib 592247835Skib if (key_max_size < length) { 593247835Skib rc = ENOSPC; 594254182Skib goto fail1; 595247835Skib } 596247835Skib memcpy(keyp, &bufferp[offset], length); 597254182Skib 598247835Skib *lengthp = length; 599247835Skib 600247835Skib return (0); 601247835Skib 602247835Skibfail1: 603247835Skib EFSYS_PROBE1(fail1, efx_rc_t, rc); 604247835Skib 605247835Skib return (rc); 606247835Skib} 607247835Skib 608247835Skib __checkReturn efx_rc_t 609247835Skibefx_lic_v1v2_write_key( 610247835Skib __in efx_nic_t *enp, 611247835Skib __in_bcount(buffer_size) 612247835Skib caddr_t bufferp, 613247835Skib __in size_t buffer_size, 614247835Skib __in uint32_t offset, 615247835Skib __in_bcount(length) caddr_t keyp, 616247835Skib __in uint32_t length, 617247835Skib __out uint32_t *lengthp 618247835Skib ) 619247835Skib{ 620247835Skib efx_rc_t rc; 621247835Skib 622247835Skib _NOTE(ARGUNUSED(enp)) 623247835Skib EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX + 624254182Skib EFX_LICENSE_V1V2_HEADER_LENGTH)); 625247835Skib 626247835Skib /* Ensure space for terminator remains */ 627247835Skib if ((offset + length) > 628247835Skib (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) { 629247835Skib rc = ENOSPC; 630247835Skib goto fail1; 631254182Skib } 632254182Skib 633247835Skib memcpy(bufferp + offset, keyp, length); 634247835Skib 635247835Skib *lengthp = length; 636247835Skib 637247835Skib return (0); 638247835Skib 639247835Skibfail1: 640247835Skib EFSYS_PROBE1(fail1, efx_rc_t, rc); 641247835Skib 642247835Skib return (rc); 643247835Skib} 644247835Skib 645247835Skib __checkReturn efx_rc_t 646247835Skibefx_lic_v1v2_delete_key( 647247835Skib __in efx_nic_t *enp, 648247835Skib __in_bcount(buffer_size) 649247835Skib caddr_t bufferp, 650247835Skib __in size_t buffer_size, 651247835Skib __in uint32_t offset, 652247835Skib __in uint32_t length, 653247835Skib __in uint32_t end, 654247835Skib __out uint32_t *deltap 655247835Skib ) 656247835Skib{ 657247835Skib uint32_t move_start = offset + length; 658247835Skib uint32_t move_length = end - move_start; 659247835Skib 660247835Skib _NOTE(ARGUNUSED(enp, buffer_size)) 661247835Skib EFSYS_ASSERT(end <= buffer_size); 662254182Skib 663247835Skib /* Shift everything after the key down */ 664247835Skib memmove(bufferp + offset, bufferp + move_start, move_length); 665247835Skib 666247835Skib *deltap = length; 667247835Skib 668247835Skib return (0); 669247835Skib} 670247835Skib 671247835Skib __checkReturn efx_rc_t 672247835Skibefx_lic_v1v2_create_partition( 673247835Skib __in efx_nic_t *enp, 674247835Skib __in_bcount(buffer_size) 675247835Skib caddr_t bufferp, 676247835Skib __in size_t buffer_size 677247835Skib ) 678247835Skib{ 679247835Skib _NOTE(ARGUNUSED(enp, buffer_size)) 680247835Skib EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size); 681247835Skib 682247835Skib /* Write terminator */ 683247835Skib memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH); 684247835Skib return (0); 685247835Skib} 686247835Skib 687247835Skib 688247835Skib __checkReturn efx_rc_t 689247835Skibefx_lic_v1v2_finish_partition( 690247835Skib __in efx_nic_t *enp, 691247835Skib __in_bcount(buffer_size) 692247835Skib caddr_t bufferp, 693247835Skib __in size_t buffer_size 694247835Skib ) 695247835Skib{ 696247835Skib _NOTE(ARGUNUSED(enp, bufferp, buffer_size)) 697247835Skib 698247835Skib return (0); 699247835Skib} 700247835Skib 701247835Skib#endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */ 702247835Skib 703247835Skib 704247835Skib/* V2 Licensing - used by Huntington family only. See SF-113611-TC */ 705247835Skib 706247835Skib#if EFSYS_OPT_HUNTINGTON 707247835Skib 708247835Skibstatic __checkReturn efx_rc_t 709247835Skibefx_mcdi_licensed_app_state( 710247835Skib __in efx_nic_t *enp, 711247835Skib __in uint64_t app_id, 712247835Skib __out boolean_t *licensedp) 713247835Skib{ 714247835Skib efx_mcdi_req_t req; 715247835Skib EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_APP_STATE_IN_LEN, 716247835Skib MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN); 717247835Skib uint32_t app_state; 718247835Skib efx_rc_t rc; 719247835Skib 720247835Skib EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); 721247835Skib 722247835Skib /* V2 licensing supports 32bit app id only */ 723254182Skib if ((app_id >> 32) != 0) { 724247835Skib rc = EINVAL; 725247835Skib goto fail1; 726247835Skib } 727247835Skib 728247835Skib req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE; 729254182Skib req.emr_in_buf = payload; 730247835Skib req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN; 731247835Skib req.emr_out_buf = payload; 732247835Skib req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN; 733247835Skib 734247835Skib MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID, 735247835Skib app_id & 0xffffffff); 736247835Skib 737247835Skib efx_mcdi_execute(enp, &req); 738247835Skib 739247835Skib if (req.emr_rc != 0) { 740247835Skib rc = req.emr_rc; 741247835Skib goto fail2; 742254182Skib } 743247835Skib 744247835Skib if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) { 745247835Skib rc = EMSGSIZE; 746247835Skib goto fail3; 747247835Skib } 748247835Skib 749247835Skib app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE)); 750247835Skib if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) { 751247835Skib *licensedp = B_TRUE; 752247835Skib } else { 753247835Skib *licensedp = B_FALSE; 754247835Skib } 755247835Skib 756247835Skib return (0); 757247835Skib 758247835Skibfail3: 759247835Skib EFSYS_PROBE(fail3); 760247835Skibfail2: 761247835Skib EFSYS_PROBE(fail2); 762247835Skibfail1: 763247835Skib EFSYS_PROBE1(fail1, efx_rc_t, rc); 764247835Skib 765247835Skib return (rc); 766247835Skib} 767247835Skib 768247835Skibstatic __checkReturn efx_rc_t 769247835Skibefx_mcdi_licensing_update_licenses( 770247835Skib __in efx_nic_t *enp) 771247835Skib{ 772247835Skib efx_mcdi_req_t req; 773247835Skib EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN, 0); 774247835Skib efx_rc_t rc; 775247835Skib 776247835Skib EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); 777247835Skib 778247835Skib req.emr_cmd = MC_CMD_LICENSING; 779247835Skib req.emr_in_buf = payload; 780247835Skib req.emr_in_length = MC_CMD_LICENSING_IN_LEN; 781247835Skib req.emr_out_buf = payload; 782247835Skib req.emr_out_length = 0; 783247835Skib 784247835Skib MCDI_IN_SET_DWORD(req, LICENSING_IN_OP, 785247835Skib MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE); 786247835Skib 787247835Skib efx_mcdi_execute(enp, &req); 788247835Skib 789247835Skib if (req.emr_rc != 0) { 790247835Skib rc = req.emr_rc; 791247835Skib goto fail1; 792247835Skib } 793247835Skib 794247835Skib if (req.emr_out_length_used != 0) { 795247835Skib rc = EIO; 796247835Skib goto fail2; 797247835Skib } 798247835Skib 799247835Skib return (0); 800247835Skib 801247835Skibfail2: 802247835Skib EFSYS_PROBE(fail2); 803247835Skibfail1: 804247835Skib EFSYS_PROBE1(fail1, efx_rc_t, rc); 805247835Skib 806247835Skib return (rc); 807247835Skib} 808247835Skib 809247835Skibstatic __checkReturn efx_rc_t 810247835Skibefx_mcdi_licensing_get_key_stats( 811247835Skib __in efx_nic_t *enp, 812247835Skib __out efx_key_stats_t *eksp) 813247835Skib{ 814247835Skib efx_mcdi_req_t req; 815247835Skib EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN, 816247835Skib MC_CMD_LICENSING_OUT_LEN); 817247835Skib efx_rc_t rc; 818247835Skib 819247835Skib EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); 820247835Skib 821247835Skib req.emr_cmd = MC_CMD_LICENSING; 822247835Skib req.emr_in_buf = payload; 823247835Skib req.emr_in_length = MC_CMD_LICENSING_IN_LEN; 824247835Skib req.emr_out_buf = payload; 825247835Skib req.emr_out_length = MC_CMD_LICENSING_OUT_LEN; 826247835Skib 827247835Skib MCDI_IN_SET_DWORD(req, LICENSING_IN_OP, 828247835Skib MC_CMD_LICENSING_IN_OP_GET_KEY_STATS); 829247835Skib 830247835Skib efx_mcdi_execute(enp, &req); 831247835Skib 832247835Skib if (req.emr_rc != 0) { 833247835Skib rc = req.emr_rc; 834247835Skib goto fail1; 835247835Skib } 836247835Skib 837247835Skib if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) { 838247835Skib rc = EMSGSIZE; 839247835Skib goto fail2; 840247835Skib } 841247835Skib 842247835Skib eksp->eks_valid = 843247835Skib MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS); 844247835Skib eksp->eks_invalid = 845247835Skib MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS); 846247835Skib eksp->eks_blacklisted = 847247835Skib MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS); 848247835Skib eksp->eks_unverifiable = 849247835Skib MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS); 850247835Skib eksp->eks_wrong_node = 851247835Skib MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS); 852247835Skib eksp->eks_licensed_apps_lo = 0; 853247835Skib eksp->eks_licensed_apps_hi = 0; 854247835Skib eksp->eks_licensed_features_lo = 0; 855247835Skib eksp->eks_licensed_features_hi = 0; 856247835Skib 857247835Skib return (0); 858247835Skib 859247835Skibfail2: 860247835Skib EFSYS_PROBE(fail2); 861247835Skibfail1: 862247835Skib EFSYS_PROBE1(fail1, efx_rc_t, rc); 863247835Skib 864247835Skib return (rc); 865247835Skib} 866247835Skib 867247835Skib#endif /* EFSYS_OPT_HUNTINGTON */ 868247835Skib 869247835Skib/* V3 Licensing - used starting from Medford family. See SF-114884-SW */ 870247835Skib 871247835Skib#if EFSYS_OPT_MEDFORD 872247835Skib 873247835Skibstatic __checkReturn efx_rc_t 874247835Skibefx_mcdi_licensing_v3_update_licenses( 875247835Skib __in efx_nic_t *enp) 876247835Skib{ 877247835Skib efx_mcdi_req_t req; 878247835Skib EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN, 0); 879247835Skib efx_rc_t rc; 880247835Skib 881247835Skib EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); 882247835Skib 883247835Skib req.emr_cmd = MC_CMD_LICENSING_V3; 884247835Skib req.emr_in_buf = payload; 885247835Skib req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN; 886 req.emr_out_buf = NULL; 887 req.emr_out_length = 0; 888 889 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP, 890 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE); 891 892 efx_mcdi_execute(enp, &req); 893 894 if (req.emr_rc != 0) { 895 rc = req.emr_rc; 896 goto fail1; 897 } 898 899 return (0); 900 901fail1: 902 EFSYS_PROBE1(fail1, efx_rc_t, rc); 903 904 return (rc); 905} 906 907static __checkReturn efx_rc_t 908efx_mcdi_licensing_v3_report_license( 909 __in efx_nic_t *enp, 910 __out efx_key_stats_t *eksp) 911{ 912 efx_mcdi_req_t req; 913 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN, 914 MC_CMD_LICENSING_V3_OUT_LEN); 915 efx_rc_t rc; 916 917 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); 918 919 req.emr_cmd = MC_CMD_LICENSING_V3; 920 req.emr_in_buf = payload; 921 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN; 922 req.emr_out_buf = payload; 923 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN; 924 925 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP, 926 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE); 927 928 efx_mcdi_execute_quiet(enp, &req); 929 930 if (req.emr_rc != 0) { 931 rc = req.emr_rc; 932 goto fail1; 933 } 934 935 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) { 936 rc = EMSGSIZE; 937 goto fail2; 938 } 939 940 eksp->eks_valid = 941 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS); 942 eksp->eks_invalid = 943 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS); 944 eksp->eks_blacklisted = 0; 945 eksp->eks_unverifiable = 946 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS); 947 eksp->eks_wrong_node = 948 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS); 949 eksp->eks_licensed_apps_lo = 950 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO); 951 eksp->eks_licensed_apps_hi = 952 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI); 953 eksp->eks_licensed_features_lo = 954 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO); 955 eksp->eks_licensed_features_hi = 956 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI); 957 958 return (0); 959 960fail2: 961 EFSYS_PROBE(fail2); 962fail1: 963 EFSYS_PROBE1(fail1, efx_rc_t, rc); 964 965 return (rc); 966} 967 968static __checkReturn efx_rc_t 969efx_mcdi_licensing_v3_app_state( 970 __in efx_nic_t *enp, 971 __in uint64_t app_id, 972 __out boolean_t *licensedp) 973{ 974 efx_mcdi_req_t req; 975 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN, 976 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN); 977 uint32_t app_state; 978 efx_rc_t rc; 979 980 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); 981 982 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE; 983 req.emr_in_buf = payload; 984 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN; 985 req.emr_out_buf = payload; 986 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN; 987 988 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO, 989 app_id & 0xffffffff); 990 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI, 991 app_id >> 32); 992 993 efx_mcdi_execute(enp, &req); 994 995 if (req.emr_rc != 0) { 996 rc = req.emr_rc; 997 goto fail1; 998 } 999 1000 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) { 1001 rc = EMSGSIZE; 1002 goto fail2; 1003 } 1004 1005 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE)); 1006 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) { 1007 *licensedp = B_TRUE; 1008 } else { 1009 *licensedp = B_FALSE; 1010 } 1011 1012 return (0); 1013 1014fail2: 1015 EFSYS_PROBE(fail2); 1016fail1: 1017 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1018 1019 return (rc); 1020} 1021 1022static __checkReturn efx_rc_t 1023efx_mcdi_licensing_v3_get_id( 1024 __in efx_nic_t *enp, 1025 __in size_t buffer_size, 1026 __out uint32_t *typep, 1027 __out size_t *lengthp, 1028 __out_bcount_part_opt(buffer_size, *lengthp) 1029 uint8_t *bufferp) 1030{ 1031 efx_mcdi_req_t req; 1032 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_GET_ID_V3_IN_LEN, 1033 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN); 1034 efx_rc_t rc; 1035 1036 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3; 1037 1038 if (bufferp == NULL) { 1039 /* Request id type and length only */ 1040 req.emr_in_buf = bufferp; 1041 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN; 1042 req.emr_out_buf = bufferp; 1043 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN; 1044 } else { 1045 /* Request full buffer */ 1046 req.emr_in_buf = bufferp; 1047 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN; 1048 req.emr_out_buf = bufferp; 1049 req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX); 1050 (void) memset(bufferp, 0, req.emr_out_length); 1051 } 1052 1053 efx_mcdi_execute_quiet(enp, &req); 1054 1055 if (req.emr_rc != 0) { 1056 rc = req.emr_rc; 1057 goto fail1; 1058 } 1059 1060 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) { 1061 rc = EMSGSIZE; 1062 goto fail2; 1063 } 1064 1065 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE); 1066 *lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH); 1067 1068 if (bufferp == NULL) { 1069 /* modify length requirements to indicate to caller the extra buffering 1070 ** needed to read the complete output. 1071 */ 1072 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN; 1073 } else { 1074 /* Shift ID down to start of buffer */ 1075 memmove(bufferp, 1076 bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST, 1077 *lengthp); 1078 memset(bufferp + (*lengthp), 0, 1079 MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST); 1080 } 1081 1082 return (0); 1083 1084fail2: 1085 EFSYS_PROBE(fail2); 1086fail1: 1087 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1088 1089 return (rc); 1090} 1091 1092/* V3 format uses Huntington TLV format partition. See SF-108797-SW */ 1093#define EFX_LICENSE_V3_KEY_LENGTH_MIN (64) 1094#define EFX_LICENSE_V3_KEY_LENGTH_MAX (160) 1095 1096 __checkReturn efx_rc_t 1097efx_lic_v3_find_start( 1098 __in efx_nic_t *enp, 1099 __in_bcount(buffer_size) 1100 caddr_t bufferp, 1101 __in size_t buffer_size, 1102 __out uint32_t *startp 1103 ) 1104{ 1105 _NOTE(ARGUNUSED(enp)) 1106 1107 return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp); 1108} 1109 1110 __checkReturn efx_rc_t 1111efx_lic_v3_find_end( 1112 __in efx_nic_t *enp, 1113 __in_bcount(buffer_size) 1114 caddr_t bufferp, 1115 __in size_t buffer_size, 1116 __in uint32_t offset, 1117 __out uint32_t *endp 1118 ) 1119{ 1120 _NOTE(ARGUNUSED(enp)) 1121 1122 return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp); 1123} 1124 1125 __checkReturn __success(return != B_FALSE) boolean_t 1126efx_lic_v3_find_key( 1127 __in efx_nic_t *enp, 1128 __in_bcount(buffer_size) 1129 caddr_t bufferp, 1130 __in size_t buffer_size, 1131 __in uint32_t offset, 1132 __out uint32_t *startp, 1133 __out uint32_t *lengthp 1134 ) 1135{ 1136 _NOTE(ARGUNUSED(enp)) 1137 1138 return ef10_nvram_buffer_find_item(bufferp, buffer_size, 1139 offset, startp, lengthp); 1140} 1141 1142 __checkReturn __success(return != B_FALSE) boolean_t 1143efx_lic_v3_validate_key( 1144 __in efx_nic_t *enp, 1145 __in_bcount(length) caddr_t keyp, 1146 __in uint32_t length 1147 ) 1148{ 1149 /* Check key is a valid V3 key */ 1150 uint8_t key_type; 1151 uint8_t key_length; 1152 1153 _NOTE(ARGUNUSED(enp)) 1154 1155 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) { 1156 goto fail1; 1157 } 1158 1159 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) { 1160 goto fail2; 1161 } 1162 1163 key_type = ((uint8_t *)keyp)[0]; 1164 key_length = ((uint8_t *)keyp)[1]; 1165 1166 if (key_type < 3) { 1167 goto fail3; 1168 } 1169 if (key_length > length) { 1170 goto fail4; 1171 } 1172 return (B_TRUE); 1173 1174fail4: 1175 EFSYS_PROBE(fail4); 1176fail3: 1177 EFSYS_PROBE(fail3); 1178fail2: 1179 EFSYS_PROBE(fail2); 1180fail1: 1181 EFSYS_PROBE1(fail1, boolean_t, B_FALSE); 1182 1183 return (B_FALSE); 1184} 1185 1186 __checkReturn efx_rc_t 1187efx_lic_v3_read_key( 1188 __in efx_nic_t *enp, 1189 __in_bcount(buffer_size) 1190 caddr_t bufferp, 1191 __in size_t buffer_size, 1192 __in uint32_t offset, 1193 __in uint32_t length, 1194 __out_bcount_part(key_max_size, *lengthp) 1195 caddr_t keyp, 1196 __in size_t key_max_size, 1197 __out uint32_t *lengthp 1198 ) 1199{ 1200 _NOTE(ARGUNUSED(enp)) 1201 1202 return ef10_nvram_buffer_get_item(bufferp, buffer_size, 1203 offset, length, keyp, key_max_size, lengthp); 1204} 1205 1206 __checkReturn efx_rc_t 1207efx_lic_v3_write_key( 1208 __in efx_nic_t *enp, 1209 __in_bcount(buffer_size) 1210 caddr_t bufferp, 1211 __in size_t buffer_size, 1212 __in uint32_t offset, 1213 __in_bcount(length) caddr_t keyp, 1214 __in uint32_t length, 1215 __out uint32_t *lengthp 1216 ) 1217{ 1218 _NOTE(ARGUNUSED(enp)) 1219 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX); 1220 1221 return ef10_nvram_buffer_insert_item(bufferp, buffer_size, 1222 offset, keyp, length, lengthp); 1223} 1224 1225 __checkReturn efx_rc_t 1226efx_lic_v3_delete_key( 1227 __in efx_nic_t *enp, 1228 __in_bcount(buffer_size) 1229 caddr_t bufferp, 1230 __in size_t buffer_size, 1231 __in uint32_t offset, 1232 __in uint32_t length, 1233 __in uint32_t end, 1234 __out uint32_t *deltap 1235 ) 1236{ 1237 efx_rc_t rc; 1238 1239 _NOTE(ARGUNUSED(enp)) 1240 1241 if ((rc = ef10_nvram_buffer_delete_item(bufferp, 1242 buffer_size, offset, length, end)) != 0) { 1243 goto fail1; 1244 } 1245 1246 *deltap = length; 1247 1248 return (0); 1249 1250fail1: 1251 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1252 1253 return (rc); 1254} 1255 1256 __checkReturn efx_rc_t 1257efx_lic_v3_create_partition( 1258 __in efx_nic_t *enp, 1259 __in_bcount(buffer_size) 1260 caddr_t bufferp, 1261 __in size_t buffer_size 1262 ) 1263{ 1264 efx_rc_t rc; 1265 1266 /* Construct empty partition */ 1267 if ((rc = ef10_nvram_buffer_create(enp, 1268 NVRAM_PARTITION_TYPE_LICENSE, 1269 bufferp, buffer_size)) != 0) { 1270 rc = EFAULT; 1271 goto fail1; 1272 } 1273 1274 return (0); 1275 1276fail1: 1277 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1278 1279 return (rc); 1280} 1281 1282 __checkReturn efx_rc_t 1283efx_lic_v3_finish_partition( 1284 __in efx_nic_t *enp, 1285 __in_bcount(buffer_size) 1286 caddr_t bufferp, 1287 __in size_t buffer_size 1288 ) 1289{ 1290 efx_rc_t rc; 1291 1292 if ((rc = ef10_nvram_buffer_finish(bufferp, 1293 buffer_size)) != 0) { 1294 goto fail1; 1295 } 1296 1297 /* Validate completed partition */ 1298 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE, 1299 bufferp, buffer_size)) != 0) { 1300 goto fail2; 1301 } 1302 1303 return (0); 1304 1305fail2: 1306 EFSYS_PROBE(fail2); 1307fail1: 1308 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1309 1310 return (rc); 1311} 1312 1313 1314#endif /* EFSYS_OPT_MEDFORD */ 1315 1316 __checkReturn efx_rc_t 1317efx_lic_init( 1318 __in efx_nic_t *enp) 1319{ 1320 const efx_lic_ops_t *elop; 1321 efx_key_stats_t eks; 1322 efx_rc_t rc; 1323 1324 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1325 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1326 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC)); 1327 1328 switch (enp->en_family) { 1329 1330#if EFSYS_OPT_SIENA 1331 case EFX_FAMILY_SIENA: 1332 elop = &__efx_lic_v1_ops; 1333 break; 1334#endif /* EFSYS_OPT_SIENA */ 1335 1336#if EFSYS_OPT_HUNTINGTON 1337 case EFX_FAMILY_HUNTINGTON: 1338 elop = &__efx_lic_v2_ops; 1339 break; 1340#endif /* EFSYS_OPT_HUNTINGTON */ 1341 1342#if EFSYS_OPT_MEDFORD 1343 case EFX_FAMILY_MEDFORD: 1344 elop = &__efx_lic_v3_ops; 1345 break; 1346#endif /* EFSYS_OPT_MEDFORD */ 1347 1348 default: 1349 EFSYS_ASSERT(0); 1350 rc = ENOTSUP; 1351 goto fail1; 1352 } 1353 1354 enp->en_elop = elop; 1355 enp->en_mod_flags |= EFX_MOD_LIC; 1356 1357 /* Probe for support */ 1358 if (efx_lic_get_key_stats(enp, &eks) == 0) { 1359 enp->en_licensing_supported = B_TRUE; 1360 } else { 1361 enp->en_licensing_supported = B_FALSE; 1362 } 1363 1364 return (0); 1365 1366fail1: 1367 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1368 1369 return (rc); 1370} 1371 1372extern __checkReturn boolean_t 1373efx_lic_check_support( 1374 __in efx_nic_t *enp) 1375{ 1376 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1377 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1378 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1379 1380 return enp->en_licensing_supported; 1381} 1382 1383 void 1384efx_lic_fini( 1385 __in efx_nic_t *enp) 1386{ 1387 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1388 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1389 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1390 1391 enp->en_elop = NULL; 1392 enp->en_mod_flags &= ~EFX_MOD_LIC; 1393} 1394 1395 1396 __checkReturn efx_rc_t 1397efx_lic_update_licenses( 1398 __in efx_nic_t *enp) 1399{ 1400 const efx_lic_ops_t *elop = enp->en_elop; 1401 efx_rc_t rc; 1402 1403 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1404 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1405 1406 if ((rc = elop->elo_update_licenses(enp)) != 0) 1407 goto fail1; 1408 1409 return (0); 1410 1411fail1: 1412 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1413 1414 return (rc); 1415} 1416 1417 __checkReturn efx_rc_t 1418efx_lic_get_key_stats( 1419 __in efx_nic_t *enp, 1420 __out efx_key_stats_t *eksp) 1421{ 1422 const efx_lic_ops_t *elop = enp->en_elop; 1423 efx_rc_t rc; 1424 1425 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1426 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1427 1428 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0) 1429 goto fail1; 1430 1431 return (0); 1432 1433fail1: 1434 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1435 1436 return (rc); 1437} 1438 1439 __checkReturn efx_rc_t 1440efx_lic_app_state( 1441 __in efx_nic_t *enp, 1442 __in uint64_t app_id, 1443 __out boolean_t *licensedp) 1444{ 1445 const efx_lic_ops_t *elop = enp->en_elop; 1446 efx_rc_t rc; 1447 1448 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1449 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1450 1451 if (elop->elo_app_state == NULL) 1452 return (ENOTSUP); 1453 1454 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0) 1455 goto fail1; 1456 1457 return (0); 1458 1459fail1: 1460 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1461 1462 return (rc); 1463} 1464 1465 __checkReturn efx_rc_t 1466efx_lic_get_id( 1467 __in efx_nic_t *enp, 1468 __in size_t buffer_size, 1469 __out uint32_t *typep, 1470 __out size_t *lengthp, 1471 __out_opt uint8_t *bufferp 1472 ) 1473{ 1474 const efx_lic_ops_t *elop = enp->en_elop; 1475 efx_rc_t rc; 1476 1477 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1478 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1479 1480 if (elop->elo_get_id == NULL) 1481 return (ENOTSUP); 1482 1483 if ((rc = elop->elo_get_id(enp, buffer_size, typep, 1484 lengthp, bufferp)) != 0) 1485 goto fail1; 1486 1487 return (0); 1488 1489fail1: 1490 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1491 1492 return (rc); 1493} 1494 1495/* Buffer management API - abstracts varying TLV format used for License partition */ 1496 1497 __checkReturn efx_rc_t 1498efx_lic_find_start( 1499 __in efx_nic_t *enp, 1500 __in_bcount(buffer_size) 1501 caddr_t bufferp, 1502 __in size_t buffer_size, 1503 __out uint32_t *startp 1504 ) 1505{ 1506 const efx_lic_ops_t *elop = enp->en_elop; 1507 efx_rc_t rc; 1508 1509 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1510 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1511 1512 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0) 1513 goto fail1; 1514 1515 return (0); 1516 1517fail1: 1518 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1519 1520 return (rc); 1521} 1522 1523 __checkReturn efx_rc_t 1524efx_lic_find_end( 1525 __in efx_nic_t *enp, 1526 __in_bcount(buffer_size) 1527 caddr_t bufferp, 1528 __in size_t buffer_size, 1529 __in uint32_t offset, 1530 __out uint32_t *endp 1531 ) 1532{ 1533 const efx_lic_ops_t *elop = enp->en_elop; 1534 efx_rc_t rc; 1535 1536 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1537 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1538 1539 if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0) 1540 goto fail1; 1541 1542 return (0); 1543 1544fail1: 1545 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1546 1547 return (rc); 1548} 1549 1550 __checkReturn __success(return != B_FALSE) boolean_t 1551efx_lic_find_key( 1552 __in efx_nic_t *enp, 1553 __in_bcount(buffer_size) 1554 caddr_t bufferp, 1555 __in size_t buffer_size, 1556 __in uint32_t offset, 1557 __out uint32_t *startp, 1558 __out uint32_t *lengthp 1559 ) 1560{ 1561 const efx_lic_ops_t *elop = enp->en_elop; 1562 1563 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1564 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1565 1566 EFSYS_ASSERT(bufferp); 1567 EFSYS_ASSERT(startp); 1568 EFSYS_ASSERT(lengthp); 1569 1570 return (elop->elo_find_key(enp, bufferp, buffer_size, offset, 1571 startp, lengthp)); 1572} 1573 1574 1575/* Validate that the buffer contains a single key in a recognised format. 1576** An empty or terminator buffer is not accepted as a valid key. 1577*/ 1578 __checkReturn __success(return != B_FALSE) boolean_t 1579efx_lic_validate_key( 1580 __in efx_nic_t *enp, 1581 __in_bcount(length) caddr_t keyp, 1582 __in uint32_t length 1583 ) 1584{ 1585 const efx_lic_ops_t *elop = enp->en_elop; 1586 boolean_t rc; 1587 1588 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1589 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1590 1591 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE) 1592 goto fail1; 1593 1594 return (B_TRUE); 1595 1596fail1: 1597 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1598 1599 return (rc); 1600} 1601 1602 __checkReturn efx_rc_t 1603efx_lic_read_key( 1604 __in efx_nic_t *enp, 1605 __in_bcount(buffer_size) 1606 caddr_t bufferp, 1607 __in size_t buffer_size, 1608 __in uint32_t offset, 1609 __in uint32_t length, 1610 __out_bcount_part(key_max_size, *lengthp) 1611 caddr_t keyp, 1612 __in size_t key_max_size, 1613 __out uint32_t *lengthp 1614 ) 1615{ 1616 const efx_lic_ops_t *elop = enp->en_elop; 1617 efx_rc_t rc; 1618 1619 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1620 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1621 1622 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset, 1623 length, keyp, key_max_size, lengthp)) != 0) 1624 goto fail1; 1625 1626 return (0); 1627 1628fail1: 1629 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1630 1631 return (rc); 1632} 1633 1634 __checkReturn efx_rc_t 1635efx_lic_write_key( 1636 __in efx_nic_t *enp, 1637 __in_bcount(buffer_size) 1638 caddr_t bufferp, 1639 __in size_t buffer_size, 1640 __in uint32_t offset, 1641 __in_bcount(length) caddr_t keyp, 1642 __in uint32_t length, 1643 __out uint32_t *lengthp 1644 ) 1645{ 1646 const efx_lic_ops_t *elop = enp->en_elop; 1647 efx_rc_t rc; 1648 1649 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1650 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1651 1652 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset, 1653 keyp, length, lengthp)) != 0) 1654 goto fail1; 1655 1656 return (0); 1657 1658fail1: 1659 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1660 1661 return (rc); 1662} 1663 1664 __checkReturn efx_rc_t 1665efx_lic_delete_key( 1666 __in efx_nic_t *enp, 1667 __in_bcount(buffer_size) 1668 caddr_t bufferp, 1669 __in size_t buffer_size, 1670 __in uint32_t offset, 1671 __in uint32_t length, 1672 __in uint32_t end, 1673 __out uint32_t *deltap 1674 ) 1675{ 1676 const efx_lic_ops_t *elop = enp->en_elop; 1677 efx_rc_t rc; 1678 1679 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1680 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1681 1682 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset, 1683 length, end, deltap)) != 0) 1684 goto fail1; 1685 1686 return (0); 1687 1688fail1: 1689 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1690 1691 return (rc); 1692} 1693 1694 __checkReturn efx_rc_t 1695efx_lic_create_partition( 1696 __in efx_nic_t *enp, 1697 __in_bcount(buffer_size) 1698 caddr_t bufferp, 1699 __in size_t buffer_size 1700 ) 1701{ 1702 const efx_lic_ops_t *elop = enp->en_elop; 1703 efx_rc_t rc; 1704 1705 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1706 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1707 1708 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0) 1709 goto fail1; 1710 1711 return (0); 1712 1713fail1: 1714 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1715 1716 return (rc); 1717} 1718 1719 1720 __checkReturn efx_rc_t 1721efx_lic_finish_partition( 1722 __in efx_nic_t *enp, 1723 __in_bcount(buffer_size) 1724 caddr_t bufferp, 1725 __in size_t buffer_size 1726 ) 1727{ 1728 const efx_lic_ops_t *elop = enp->en_elop; 1729 efx_rc_t rc; 1730 1731 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1732 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1733 1734 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0) 1735 goto fail1; 1736 1737 return (0); 1738 1739fail1: 1740 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1741 1742 return (rc); 1743} 1744 1745#endif /* EFSYS_OPT_LICENSING */ 1746