1/*- 2 * Copyright (c) 2009-2016 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 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. 13 * 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. 25 * 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. 29 */ 30 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/common/efx_lic.c 342516 2018-12-26 10:25:01Z arybchik $"); 33 34#include "efx.h" 35#include "efx_impl.h" 36 37#if EFSYS_OPT_LICENSING 38 39#include "ef10_tlv_layout.h" 40 41#if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON 42 43 __checkReturn efx_rc_t 44efx_lic_v1v2_find_start( 45 __in efx_nic_t *enp, 46 __in_bcount(buffer_size) 47 caddr_t bufferp, 48 __in size_t buffer_size, 49 __out uint32_t *startp 50 ); 51 52 __checkReturn efx_rc_t 53efx_lic_v1v2_find_end( 54 __in efx_nic_t *enp, 55 __in_bcount(buffer_size) 56 caddr_t bufferp, 57 __in size_t buffer_size, 58 __in uint32_t offset, 59 __out uint32_t *endp 60 ); 61 62 __checkReturn __success(return != B_FALSE) boolean_t 63efx_lic_v1v2_find_key( 64 __in efx_nic_t *enp, 65 __in_bcount(buffer_size) 66 caddr_t bufferp, 67 __in size_t buffer_size, 68 __in uint32_t offset, 69 __out uint32_t *startp, 70 __out uint32_t *lengthp 71 ); 72 73 __checkReturn __success(return != B_FALSE) boolean_t 74efx_lic_v1v2_validate_key( 75 __in efx_nic_t *enp, 76 __in_bcount(length) caddr_t keyp, 77 __in uint32_t length 78 ); 79 80 __checkReturn efx_rc_t 81efx_lic_v1v2_read_key( 82 __in efx_nic_t *enp, 83 __in_bcount(buffer_size) 84 caddr_t bufferp, 85 __in size_t buffer_size, 86 __in uint32_t offset, 87 __in uint32_t length, 88 __out_bcount_part(key_max_size, *lengthp) 89 caddr_t keyp, 90 __in size_t key_max_size, 91 __out uint32_t *lengthp 92 ); 93 94 __checkReturn efx_rc_t 95efx_lic_v1v2_write_key( 96 __in efx_nic_t *enp, 97 __in_bcount(buffer_size) 98 caddr_t bufferp, 99 __in size_t buffer_size, 100 __in uint32_t offset, 101 __in_bcount(length) caddr_t keyp, 102 __in uint32_t length, 103 __out uint32_t *lengthp 104 ); 105 106 __checkReturn efx_rc_t 107efx_lic_v1v2_delete_key( 108 __in efx_nic_t *enp, 109 __in_bcount(buffer_size) 110 caddr_t bufferp, 111 __in size_t buffer_size, 112 __in uint32_t offset, 113 __in uint32_t length, 114 __in uint32_t end, 115 __out uint32_t *deltap 116 ); 117 118 __checkReturn efx_rc_t 119efx_lic_v1v2_create_partition( 120 __in efx_nic_t *enp, 121 __in_bcount(buffer_size) 122 caddr_t bufferp, 123 __in size_t buffer_size 124 ); 125 126 __checkReturn efx_rc_t 127efx_lic_v1v2_finish_partition( 128 __in efx_nic_t *enp, 129 __in_bcount(buffer_size) 130 caddr_t bufferp, 131 __in size_t buffer_size 132 ); 133 134#endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */ 135 136 137#if EFSYS_OPT_SIENA 138 139static __checkReturn efx_rc_t 140efx_mcdi_fc_license_update_license( 141 __in efx_nic_t *enp); 142 143static __checkReturn efx_rc_t 144efx_mcdi_fc_license_get_key_stats( 145 __in efx_nic_t *enp, 146 __out efx_key_stats_t *eksp); 147 148static const efx_lic_ops_t __efx_lic_v1_ops = { 149 efx_mcdi_fc_license_update_license, /* elo_update_licenses */ 150 efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */ 151 NULL, /* elo_app_state */ 152 NULL, /* elo_get_id */ 153 efx_lic_v1v2_find_start, /* elo_find_start */ 154 efx_lic_v1v2_find_end, /* elo_find_end */ 155 efx_lic_v1v2_find_key, /* elo_find_key */ 156 efx_lic_v1v2_validate_key, /* elo_validate_key */ 157 efx_lic_v1v2_read_key, /* elo_read_key */ 158 efx_lic_v1v2_write_key, /* elo_write_key */ 159 efx_lic_v1v2_delete_key, /* elo_delete_key */ 160 efx_lic_v1v2_create_partition, /* elo_create_partition */ 161 efx_lic_v1v2_finish_partition, /* elo_finish_partition */ 162}; 163 164#endif /* EFSYS_OPT_SIENA */ 165 166#if EFSYS_OPT_HUNTINGTON 167 168static __checkReturn efx_rc_t 169efx_mcdi_licensing_update_licenses( 170 __in efx_nic_t *enp); 171 172static __checkReturn efx_rc_t 173efx_mcdi_licensing_get_key_stats( 174 __in efx_nic_t *enp, 175 __out efx_key_stats_t *eksp); 176 177static __checkReturn efx_rc_t 178efx_mcdi_licensed_app_state( 179 __in efx_nic_t *enp, 180 __in uint64_t app_id, 181 __out boolean_t *licensedp); 182 183static const efx_lic_ops_t __efx_lic_v2_ops = { 184 efx_mcdi_licensing_update_licenses, /* elo_update_licenses */ 185 efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */ 186 efx_mcdi_licensed_app_state, /* elo_app_state */ 187 NULL, /* elo_get_id */ 188 efx_lic_v1v2_find_start, /* elo_find_start */ 189 efx_lic_v1v2_find_end, /* elo_find_end */ 190 efx_lic_v1v2_find_key, /* elo_find_key */ 191 efx_lic_v1v2_validate_key, /* elo_validate_key */ 192 efx_lic_v1v2_read_key, /* elo_read_key */ 193 efx_lic_v1v2_write_key, /* elo_write_key */ 194 efx_lic_v1v2_delete_key, /* elo_delete_key */ 195 efx_lic_v1v2_create_partition, /* elo_create_partition */ 196 efx_lic_v1v2_finish_partition, /* elo_finish_partition */ 197}; 198 199#endif /* EFSYS_OPT_HUNTINGTON */ 200 201#if EFSYS_OPT_MEDFORD 202 203static __checkReturn efx_rc_t 204efx_mcdi_licensing_v3_update_licenses( 205 __in efx_nic_t *enp); 206 207static __checkReturn efx_rc_t 208efx_mcdi_licensing_v3_report_license( 209 __in efx_nic_t *enp, 210 __out efx_key_stats_t *eksp); 211 212static __checkReturn efx_rc_t 213efx_mcdi_licensing_v3_app_state( 214 __in efx_nic_t *enp, 215 __in uint64_t app_id, 216 __out boolean_t *licensedp); 217 218static __checkReturn efx_rc_t 219efx_mcdi_licensing_v3_get_id( 220 __in efx_nic_t *enp, 221 __in size_t buffer_size, 222 __out uint32_t *typep, 223 __out size_t *lengthp, 224 __out_bcount_part_opt(buffer_size, *lengthp) 225 uint8_t *bufferp); 226 227 __checkReturn efx_rc_t 228efx_lic_v3_find_start( 229 __in efx_nic_t *enp, 230 __in_bcount(buffer_size) 231 caddr_t bufferp, 232 __in size_t buffer_size, 233 __out uint32_t *startp 234 ); 235 236 __checkReturn efx_rc_t 237efx_lic_v3_find_end( 238 __in efx_nic_t *enp, 239 __in_bcount(buffer_size) 240 caddr_t bufferp, 241 __in size_t buffer_size, 242 __in uint32_t offset, 243 __out uint32_t *endp 244 ); 245 246 __checkReturn __success(return != B_FALSE) boolean_t 247efx_lic_v3_find_key( 248 __in efx_nic_t *enp, 249 __in_bcount(buffer_size) 250 caddr_t bufferp, 251 __in size_t buffer_size, 252 __in uint32_t offset, 253 __out uint32_t *startp, 254 __out uint32_t *lengthp 255 ); 256 257 __checkReturn __success(return != B_FALSE) boolean_t 258efx_lic_v3_validate_key( 259 __in efx_nic_t *enp, 260 __in_bcount(length) caddr_t keyp, 261 __in uint32_t length 262 ); 263 264 __checkReturn efx_rc_t 265efx_lic_v3_read_key( 266 __in efx_nic_t *enp, 267 __in_bcount(buffer_size) 268 caddr_t bufferp, 269 __in size_t buffer_size, 270 __in uint32_t offset, 271 __in uint32_t length, 272 __out_bcount_part(key_max_size, *lengthp) 273 caddr_t keyp, 274 __in size_t key_max_size, 275 __out uint32_t *lengthp 276 ); 277 278 __checkReturn efx_rc_t 279efx_lic_v3_write_key( 280 __in efx_nic_t *enp, 281 __in_bcount(buffer_size) 282 caddr_t bufferp, 283 __in size_t buffer_size, 284 __in uint32_t offset, 285 __in_bcount(length) caddr_t keyp, 286 __in uint32_t length, 287 __out uint32_t *lengthp 288 ); 289 290 __checkReturn efx_rc_t 291efx_lic_v3_delete_key( 292 __in efx_nic_t *enp, 293 __in_bcount(buffer_size) 294 caddr_t bufferp, 295 __in size_t buffer_size, 296 __in uint32_t offset, 297 __in uint32_t length, 298 __in uint32_t end, 299 __out uint32_t *deltap 300 ); 301 302 __checkReturn efx_rc_t 303efx_lic_v3_create_partition( 304 __in efx_nic_t *enp, 305 __in_bcount(buffer_size) 306 caddr_t bufferp, 307 __in size_t buffer_size 308 ); 309 310 __checkReturn efx_rc_t 311efx_lic_v3_finish_partition( 312 __in efx_nic_t *enp, 313 __in_bcount(buffer_size) 314 caddr_t bufferp, 315 __in size_t buffer_size 316 ); 317 318static const efx_lic_ops_t __efx_lic_v3_ops = { 319 efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */ 320 efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */ 321 efx_mcdi_licensing_v3_app_state, /* elo_app_state */ 322 efx_mcdi_licensing_v3_get_id, /* elo_get_id */ 323 efx_lic_v3_find_start, /* elo_find_start*/ 324 efx_lic_v3_find_end, /* elo_find_end */ 325 efx_lic_v3_find_key, /* elo_find_key */ 326 efx_lic_v3_validate_key, /* elo_validate_key */ 327 efx_lic_v3_read_key, /* elo_read_key */ 328 efx_lic_v3_write_key, /* elo_write_key */ 329 efx_lic_v3_delete_key, /* elo_delete_key */ 330 efx_lic_v3_create_partition, /* elo_create_partition */ 331 efx_lic_v3_finish_partition, /* elo_finish_partition */ 332}; 333 334#endif /* EFSYS_OPT_MEDFORD */ 335 336 337/* V1 Licensing - used in Siena Modena only */ 338 339#if EFSYS_OPT_SIENA 340 341static __checkReturn efx_rc_t 342efx_mcdi_fc_license_update_license( 343 __in efx_nic_t *enp) 344{ 345 efx_mcdi_req_t req; 346 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN, 0); 347 efx_rc_t rc; 348 349 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 350 351 req.emr_cmd = MC_CMD_FC; 352 req.emr_in_buf = payload; 353 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN; 354 req.emr_out_buf = payload; 355 req.emr_out_length = 0; 356 357 MCDI_IN_SET_DWORD(req, FC_IN_CMD, 358 MC_CMD_FC_OP_LICENSE); 359 360 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP, 361 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE); 362 363 efx_mcdi_execute(enp, &req); 364 365 if (req.emr_rc != 0) { 366 rc = req.emr_rc; 367 goto fail1; 368 } 369 370 if (req.emr_out_length_used != 0) { 371 rc = EIO; 372 goto fail2; 373 } 374 375 return (0); 376 377fail2: 378 EFSYS_PROBE(fail2); 379fail1: 380 EFSYS_PROBE1(fail1, efx_rc_t, rc); 381 382 return (rc); 383} 384 385static __checkReturn efx_rc_t 386efx_mcdi_fc_license_get_key_stats( 387 __in efx_nic_t *enp, 388 __out efx_key_stats_t *eksp) 389{ 390 efx_mcdi_req_t req; 391 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FC_IN_LICENSE_LEN, 392 MC_CMD_FC_OUT_LICENSE_LEN); 393 efx_rc_t rc; 394 395 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 396 397 req.emr_cmd = MC_CMD_FC; 398 req.emr_in_buf = payload; 399 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN; 400 req.emr_out_buf = payload; 401 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN; 402 403 MCDI_IN_SET_DWORD(req, FC_IN_CMD, 404 MC_CMD_FC_OP_LICENSE); 405 406 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP, 407 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS); 408 409 efx_mcdi_execute_quiet(enp, &req); 410 411 if (req.emr_rc != 0) { 412 rc = req.emr_rc; 413 goto fail1; 414 } 415 416 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) { 417 rc = EMSGSIZE; 418 goto fail2; 419 } 420 421 eksp->eks_valid = 422 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS); 423 eksp->eks_invalid = 424 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS); 425 eksp->eks_blacklisted = 426 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS); 427 eksp->eks_unverifiable = 0; 428 eksp->eks_wrong_node = 0; 429 eksp->eks_licensed_apps_lo = 0; 430 eksp->eks_licensed_apps_hi = 0; 431 eksp->eks_licensed_features_lo = 0; 432 eksp->eks_licensed_features_hi = 0; 433 434 return (0); 435 436fail2: 437 EFSYS_PROBE(fail2); 438fail1: 439 EFSYS_PROBE1(fail1, efx_rc_t, rc); 440 441 return (rc); 442} 443 444#endif /* EFSYS_OPT_SIENA */ 445 446/* V1 and V2 Partition format - based on a 16-bit TLV format */ 447 448#if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON 449 450/* 451 * V1/V2 format - defined in SF-108542-TC section 4.2: 452 * Type (T): 16bit - revision/HMAC algorithm 453 * Length (L): 16bit - value length in bytes 454 * Value (V): L bytes - payload 455 */ 456#define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256) 457#define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof(uint16_t)) 458 459 __checkReturn efx_rc_t 460efx_lic_v1v2_find_start( 461 __in efx_nic_t *enp, 462 __in_bcount(buffer_size) 463 caddr_t bufferp, 464 __in size_t buffer_size, 465 __out uint32_t *startp 466 ) 467{ 468 _NOTE(ARGUNUSED(enp, bufferp, buffer_size)) 469 470 *startp = 0; 471 return (0); 472} 473 474 __checkReturn efx_rc_t 475efx_lic_v1v2_find_end( 476 __in efx_nic_t *enp, 477 __in_bcount(buffer_size) 478 caddr_t bufferp, 479 __in size_t buffer_size, 480 __in uint32_t offset, 481 __out uint32_t *endp 482 ) 483{ 484 _NOTE(ARGUNUSED(enp, bufferp, buffer_size)) 485 486 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH; 487 return (0); 488} 489 490 __checkReturn __success(return != B_FALSE) boolean_t 491efx_lic_v1v2_find_key( 492 __in efx_nic_t *enp, 493 __in_bcount(buffer_size) 494 caddr_t bufferp, 495 __in size_t buffer_size, 496 __in uint32_t offset, 497 __out uint32_t *startp, 498 __out uint32_t *lengthp 499 ) 500{ 501 boolean_t found; 502 uint16_t tlv_type; 503 uint16_t tlv_length; 504 505 _NOTE(ARGUNUSED(enp)) 506 507 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH) 508 goto fail1; 509 510 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]); 511 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]); 512 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) || 513 (tlv_type == 0 && tlv_length == 0)) { 514 found = B_FALSE; 515 } else { 516 *startp = offset; 517 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH; 518 found = B_TRUE; 519 } 520 return (found); 521 522fail1: 523 EFSYS_PROBE1(fail1, boolean_t, B_FALSE); 524 525 return (B_FALSE); 526} 527 528 __checkReturn __success(return != B_FALSE) boolean_t 529efx_lic_v1v2_validate_key( 530 __in efx_nic_t *enp, 531 __in_bcount(length) caddr_t keyp, 532 __in uint32_t length 533 ) 534{ 535 uint16_t tlv_type; 536 uint16_t tlv_length; 537 538 _NOTE(ARGUNUSED(enp)) 539 540 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) { 541 goto fail1; 542 } 543 544 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]); 545 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]); 546 547 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) { 548 goto fail2; 549 } 550 if (tlv_type == 0) { 551 goto fail3; 552 } 553 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) { 554 goto fail4; 555 } 556 557 return (B_TRUE); 558 559fail4: 560 EFSYS_PROBE(fail4); 561fail3: 562 EFSYS_PROBE(fail3); 563fail2: 564 EFSYS_PROBE(fail2); 565fail1: 566 EFSYS_PROBE1(fail1, boolean_t, B_FALSE); 567 568 return (B_FALSE); 569} 570 571 572 __checkReturn efx_rc_t 573efx_lic_v1v2_read_key( 574 __in efx_nic_t *enp, 575 __in_bcount(buffer_size) 576 caddr_t bufferp, 577 __in size_t buffer_size, 578 __in uint32_t offset, 579 __in uint32_t length, 580 __out_bcount_part(key_max_size, *lengthp) 581 caddr_t keyp, 582 __in size_t key_max_size, 583 __out uint32_t *lengthp 584 ) 585{ 586 efx_rc_t rc; 587 588 _NOTE(ARGUNUSED(enp, buffer_size)) 589 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX + 590 EFX_LICENSE_V1V2_HEADER_LENGTH)); 591 592 if (key_max_size < length) { 593 rc = ENOSPC; 594 goto fail1; 595 } 596 memcpy(keyp, &bufferp[offset], length); 597 598 *lengthp = length; 599 600 return (0); 601 602fail1: 603 EFSYS_PROBE1(fail1, efx_rc_t, rc); 604 605 return (rc); 606} 607 608 __checkReturn efx_rc_t 609efx_lic_v1v2_write_key( 610 __in efx_nic_t *enp, 611 __in_bcount(buffer_size) 612 caddr_t bufferp, 613 __in size_t buffer_size, 614 __in uint32_t offset, 615 __in_bcount(length) caddr_t keyp, 616 __in uint32_t length, 617 __out uint32_t *lengthp 618 ) 619{ 620 efx_rc_t rc; 621 622 _NOTE(ARGUNUSED(enp)) 623 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX + 624 EFX_LICENSE_V1V2_HEADER_LENGTH)); 625 626 /* Ensure space for terminator remains */ 627 if ((offset + length) > 628 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) { 629 rc = ENOSPC; 630 goto fail1; 631 } 632 633 memcpy(bufferp + offset, keyp, length); 634 635 *lengthp = length; 636 637 return (0); 638 639fail1: 640 EFSYS_PROBE1(fail1, efx_rc_t, rc); 641 642 return (rc); 643} 644 645 __checkReturn efx_rc_t 646efx_lic_v1v2_delete_key( 647 __in efx_nic_t *enp, 648 __in_bcount(buffer_size) 649 caddr_t bufferp, 650 __in size_t buffer_size, 651 __in uint32_t offset, 652 __in uint32_t length, 653 __in uint32_t end, 654 __out uint32_t *deltap 655 ) 656{ 657 uint32_t move_start = offset + length; 658 uint32_t move_length = end - move_start; 659 660 _NOTE(ARGUNUSED(enp, buffer_size)) 661 EFSYS_ASSERT(end <= buffer_size); 662 663 /* Shift everything after the key down */ 664 memmove(bufferp + offset, bufferp + move_start, move_length); 665 666 *deltap = length; 667 668 return (0); 669} 670 671 __checkReturn efx_rc_t 672efx_lic_v1v2_create_partition( 673 __in efx_nic_t *enp, 674 __in_bcount(buffer_size) 675 caddr_t bufferp, 676 __in size_t buffer_size 677 ) 678{ 679 _NOTE(ARGUNUSED(enp, buffer_size)) 680 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size); 681 682 /* Write terminator */ 683 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH); 684 return (0); 685} 686 687 688 __checkReturn efx_rc_t 689efx_lic_v1v2_finish_partition( 690 __in efx_nic_t *enp, 691 __in_bcount(buffer_size) 692 caddr_t bufferp, 693 __in size_t buffer_size 694 ) 695{ 696 _NOTE(ARGUNUSED(enp, bufferp, buffer_size)) 697 698 return (0); 699} 700 701#endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */ 702 703 704/* V2 Licensing - used by Huntington family only. See SF-113611-TC */ 705 706#if EFSYS_OPT_HUNTINGTON 707 708static __checkReturn efx_rc_t 709efx_mcdi_licensed_app_state( 710 __in efx_nic_t *enp, 711 __in uint64_t app_id, 712 __out boolean_t *licensedp) 713{ 714 efx_mcdi_req_t req; 715 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LICENSED_APP_STATE_IN_LEN, 716 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN); 717 uint32_t app_state; 718 efx_rc_t rc; 719 720 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); 721 722 /* V2 licensing supports 32bit app id only */ 723 if ((app_id >> 32) != 0) { 724 rc = EINVAL; 725 goto fail1; 726 } 727 728 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE; 729 req.emr_in_buf = payload; 730 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN; 731 req.emr_out_buf = payload; 732 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN; 733 734 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID, 735 app_id & 0xffffffff); 736 737 efx_mcdi_execute(enp, &req); 738 739 if (req.emr_rc != 0) { 740 rc = req.emr_rc; 741 goto fail2; 742 } 743 744 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) { 745 rc = EMSGSIZE; 746 goto fail3; 747 } 748 749 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE)); 750 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) { 751 *licensedp = B_TRUE; 752 } else { 753 *licensedp = B_FALSE; 754 } 755 756 return (0); 757 758fail3: 759 EFSYS_PROBE(fail3); 760fail2: 761 EFSYS_PROBE(fail2); 762fail1: 763 EFSYS_PROBE1(fail1, efx_rc_t, rc); 764 765 return (rc); 766} 767 768static __checkReturn efx_rc_t 769efx_mcdi_licensing_update_licenses( 770 __in efx_nic_t *enp) 771{ 772 efx_mcdi_req_t req; 773 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN, 0); 774 efx_rc_t rc; 775 776 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); 777 778 req.emr_cmd = MC_CMD_LICENSING; 779 req.emr_in_buf = payload; 780 req.emr_in_length = MC_CMD_LICENSING_IN_LEN; 781 req.emr_out_buf = payload; 782 req.emr_out_length = 0; 783 784 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP, 785 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE); 786 787 efx_mcdi_execute(enp, &req); 788 789 if (req.emr_rc != 0) { 790 rc = req.emr_rc; 791 goto fail1; 792 } 793 794 if (req.emr_out_length_used != 0) { 795 rc = EIO; 796 goto fail2; 797 } 798 799 return (0); 800 801fail2: 802 EFSYS_PROBE(fail2); 803fail1: 804 EFSYS_PROBE1(fail1, efx_rc_t, rc); 805 806 return (rc); 807} 808 809static __checkReturn efx_rc_t 810efx_mcdi_licensing_get_key_stats( 811 __in efx_nic_t *enp, 812 __out efx_key_stats_t *eksp) 813{ 814 efx_mcdi_req_t req; 815 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_IN_LEN, 816 MC_CMD_LICENSING_OUT_LEN); 817 efx_rc_t rc; 818 819 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); 820 821 req.emr_cmd = MC_CMD_LICENSING; 822 req.emr_in_buf = payload; 823 req.emr_in_length = MC_CMD_LICENSING_IN_LEN; 824 req.emr_out_buf = payload; 825 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN; 826 827 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP, 828 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS); 829 830 efx_mcdi_execute(enp, &req); 831 832 if (req.emr_rc != 0) { 833 rc = req.emr_rc; 834 goto fail1; 835 } 836 837 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) { 838 rc = EMSGSIZE; 839 goto fail2; 840 } 841 842 eksp->eks_valid = 843 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS); 844 eksp->eks_invalid = 845 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS); 846 eksp->eks_blacklisted = 847 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS); 848 eksp->eks_unverifiable = 849 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS); 850 eksp->eks_wrong_node = 851 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS); 852 eksp->eks_licensed_apps_lo = 0; 853 eksp->eks_licensed_apps_hi = 0; 854 eksp->eks_licensed_features_lo = 0; 855 eksp->eks_licensed_features_hi = 0; 856 857 return (0); 858 859fail2: 860 EFSYS_PROBE(fail2); 861fail1: 862 EFSYS_PROBE1(fail1, efx_rc_t, rc); 863 864 return (rc); 865} 866 867#endif /* EFSYS_OPT_HUNTINGTON */ 868 869/* V3 Licensing - used starting from Medford family. See SF-114884-SW */ 870 871#if EFSYS_OPT_MEDFORD 872 873static __checkReturn efx_rc_t 874efx_mcdi_licensing_v3_update_licenses( 875 __in efx_nic_t *enp) 876{ 877 efx_mcdi_req_t req; 878 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LICENSING_V3_IN_LEN, 0); 879 efx_rc_t rc; 880 881 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); 882 883 req.emr_cmd = MC_CMD_LICENSING_V3; 884 req.emr_in_buf = payload; 885 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