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$"); 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 44 efx_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 53 efx_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 63 efx_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 74 efx_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 81 efx_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 95 efx_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 107 efx_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 119 efx_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 127 efx_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 139 static __checkReturn efx_rc_t 140 efx_mcdi_fc_license_update_license( 141 __in efx_nic_t *enp); 142 143 static __checkReturn efx_rc_t 144 efx_mcdi_fc_license_get_key_stats( 145 __in efx_nic_t *enp, 146 __out efx_key_stats_t *eksp); 147 148 static 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 168 static __checkReturn efx_rc_t 169 efx_mcdi_licensing_update_licenses( 170 __in efx_nic_t *enp); 171 172 static __checkReturn efx_rc_t 173 efx_mcdi_licensing_get_key_stats( 174 __in efx_nic_t *enp, 175 __out efx_key_stats_t *eksp); 176 177 static __checkReturn efx_rc_t 178 efx_mcdi_licensed_app_state( 179 __in efx_nic_t *enp, 180 __in uint64_t app_id, 181 __out boolean_t *licensedp); 182 183 static 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 203 static __checkReturn efx_rc_t 204 efx_mcdi_licensing_v3_update_licenses( 205 __in efx_nic_t *enp); 206 207 static __checkReturn efx_rc_t 208 efx_mcdi_licensing_v3_report_license( 209 __in efx_nic_t *enp, 210 __out efx_key_stats_t *eksp); 211 212 static __checkReturn efx_rc_t 213 efx_mcdi_licensing_v3_app_state( 214 __in efx_nic_t *enp, 215 __in uint64_t app_id, 216 __out boolean_t *licensedp); 217 218 static __checkReturn efx_rc_t 219 efx_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 228 efx_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 237 efx_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 247 efx_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 258 efx_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 265 efx_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 279 efx_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 291 efx_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 303 efx_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 311 efx_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 318 static 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 341 static __checkReturn efx_rc_t 342 efx_mcdi_fc_license_update_license( 343 __in efx_nic_t *enp) 344 { 345 efx_mcdi_req_t req; 346 uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN]; 347 efx_rc_t rc; 348 349 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 350 351 (void) memset(payload, 0, sizeof (payload)); 352 req.emr_cmd = MC_CMD_FC; 353 req.emr_in_buf = payload; 354 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN; 355 req.emr_out_buf = payload; 356 req.emr_out_length = 0; 357 358 MCDI_IN_SET_DWORD(req, FC_IN_CMD, 359 MC_CMD_FC_OP_LICENSE); 360 361 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP, 362 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE); 363 364 efx_mcdi_execute(enp, &req); 365 366 if (req.emr_rc != 0) { 367 rc = req.emr_rc; 368 goto fail1; 369 } 370 371 if (req.emr_out_length_used != 0) { 372 rc = EIO; 373 goto fail2; 374 } 375 376 return (0); 377 378 fail2: 379 EFSYS_PROBE(fail2); 380 fail1: 381 EFSYS_PROBE1(fail1, efx_rc_t, rc); 382 383 return (rc); 384 } 385 386 static __checkReturn efx_rc_t 387 efx_mcdi_fc_license_get_key_stats( 388 __in efx_nic_t *enp, 389 __out efx_key_stats_t *eksp) 390 { 391 efx_mcdi_req_t req; 392 uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN, 393 MC_CMD_FC_OUT_LICENSE_LEN)]; 394 efx_rc_t rc; 395 396 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 397 398 (void) memset(payload, 0, sizeof (payload)); 399 req.emr_cmd = MC_CMD_FC; 400 req.emr_in_buf = payload; 401 req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN; 402 req.emr_out_buf = payload; 403 req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN; 404 405 MCDI_IN_SET_DWORD(req, FC_IN_CMD, 406 MC_CMD_FC_OP_LICENSE); 407 408 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP, 409 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS); 410 411 efx_mcdi_execute_quiet(enp, &req); 412 413 if (req.emr_rc != 0) { 414 rc = req.emr_rc; 415 goto fail1; 416 } 417 418 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) { 419 rc = EMSGSIZE; 420 goto fail2; 421 } 422 423 eksp->eks_valid = 424 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS); 425 eksp->eks_invalid = 426 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS); 427 eksp->eks_blacklisted = 428 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS); 429 eksp->eks_unverifiable = 0; 430 eksp->eks_wrong_node = 0; 431 eksp->eks_licensed_apps_lo = 0; 432 eksp->eks_licensed_apps_hi = 0; 433 eksp->eks_licensed_features_lo = 0; 434 eksp->eks_licensed_features_hi = 0; 435 436 return (0); 437 438 fail2: 439 EFSYS_PROBE(fail2); 440 fail1: 441 EFSYS_PROBE1(fail1, efx_rc_t, rc); 442 443 return (rc); 444 } 445 446 #endif /* EFSYS_OPT_SIENA */ 447 448 /* V1 and V2 Partition format - based on a 16-bit TLV format */ 449 450 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON 451 452 /* 453 * V1/V2 format - defined in SF-108542-TC section 4.2: 454 * Type (T): 16bit - revision/HMAC algorithm 455 * Length (L): 16bit - value length in bytes 456 * Value (V): L bytes - payload 457 */ 458 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX (256) 459 #define EFX_LICENSE_V1V2_HEADER_LENGTH (2 * sizeof(uint16_t)) 460 461 __checkReturn efx_rc_t 462 efx_lic_v1v2_find_start( 463 __in efx_nic_t *enp, 464 __in_bcount(buffer_size) 465 caddr_t bufferp, 466 __in size_t buffer_size, 467 __out uint32_t *startp 468 ) 469 { 470 _NOTE(ARGUNUSED(enp, bufferp, buffer_size)) 471 472 *startp = 0; 473 return (0); 474 } 475 476 __checkReturn efx_rc_t 477 efx_lic_v1v2_find_end( 478 __in efx_nic_t *enp, 479 __in_bcount(buffer_size) 480 caddr_t bufferp, 481 __in size_t buffer_size, 482 __in uint32_t offset, 483 __out uint32_t *endp 484 ) 485 { 486 _NOTE(ARGUNUSED(enp, bufferp, buffer_size)) 487 488 *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH; 489 return (0); 490 } 491 492 __checkReturn __success(return != B_FALSE) boolean_t 493 efx_lic_v1v2_find_key( 494 __in efx_nic_t *enp, 495 __in_bcount(buffer_size) 496 caddr_t bufferp, 497 __in size_t buffer_size, 498 __in uint32_t offset, 499 __out uint32_t *startp, 500 __out uint32_t *lengthp 501 ) 502 { 503 boolean_t found; 504 uint16_t tlv_type; 505 uint16_t tlv_length; 506 507 _NOTE(ARGUNUSED(enp)) 508 509 if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH) 510 goto fail1; 511 512 tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]); 513 tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]); 514 if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) || 515 (tlv_type == 0 && tlv_length == 0)) { 516 found = B_FALSE; 517 } else { 518 *startp = offset; 519 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH; 520 found = B_TRUE; 521 } 522 return (found); 523 524 fail1: 525 EFSYS_PROBE(fail1); 526 527 return (B_FALSE); 528 } 529 530 __checkReturn __success(return != B_FALSE) boolean_t 531 efx_lic_v1v2_validate_key( 532 __in efx_nic_t *enp, 533 __in_bcount(length) caddr_t keyp, 534 __in uint32_t length 535 ) 536 { 537 uint16_t tlv_type; 538 uint16_t tlv_length; 539 540 _NOTE(ARGUNUSED(enp)) 541 542 if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) { 543 goto fail1; 544 } 545 546 tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]); 547 tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]); 548 549 if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) { 550 goto fail2; 551 } 552 if (tlv_type == 0) { 553 goto fail3; 554 } 555 if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) { 556 goto fail4; 557 } 558 559 return (B_TRUE); 560 561 fail4: 562 EFSYS_PROBE(fail4); 563 fail3: 564 EFSYS_PROBE(fail3); 565 fail2: 566 EFSYS_PROBE(fail2); 567 fail1: 568 EFSYS_PROBE(fail1); 569 570 return (B_FALSE); 571 } 572 573 574 __checkReturn efx_rc_t 575 efx_lic_v1v2_read_key( 576 __in efx_nic_t *enp, 577 __in_bcount(buffer_size) 578 caddr_t bufferp, 579 __in size_t buffer_size, 580 __in uint32_t offset, 581 __in uint32_t length, 582 __out_bcount_part(key_max_size, *lengthp) 583 caddr_t keyp, 584 __in size_t key_max_size, 585 __out uint32_t *lengthp 586 ) 587 { 588 efx_rc_t rc; 589 590 _NOTE(ARGUNUSED(enp)) 591 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX + 592 EFX_LICENSE_V1V2_HEADER_LENGTH)); 593 594 if (key_max_size < length) { 595 rc = ENOSPC; 596 goto fail1; 597 } 598 memcpy(keyp, &bufferp[offset], length); 599 600 *lengthp = length; 601 602 return (0); 603 604 fail1: 605 EFSYS_PROBE1(fail1, efx_rc_t, rc); 606 607 return (rc); 608 } 609 610 __checkReturn efx_rc_t 611 efx_lic_v1v2_write_key( 612 __in efx_nic_t *enp, 613 __in_bcount(buffer_size) 614 caddr_t bufferp, 615 __in size_t buffer_size, 616 __in uint32_t offset, 617 __in_bcount(length) caddr_t keyp, 618 __in uint32_t length, 619 __out uint32_t *lengthp 620 ) 621 { 622 efx_rc_t rc; 623 624 _NOTE(ARGUNUSED(enp)) 625 EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX + 626 EFX_LICENSE_V1V2_HEADER_LENGTH)); 627 628 /* Ensure space for terminator remains */ 629 if ((offset + length) > 630 (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) { 631 rc = ENOSPC; 632 goto fail1; 633 } 634 635 memcpy(bufferp + offset, keyp, length); 636 637 *lengthp = length; 638 639 return (0); 640 641 fail1: 642 EFSYS_PROBE1(fail1, efx_rc_t, rc); 643 644 return (rc); 645 } 646 647 __checkReturn efx_rc_t 648 efx_lic_v1v2_delete_key( 649 __in efx_nic_t *enp, 650 __in_bcount(buffer_size) 651 caddr_t bufferp, 652 __in size_t buffer_size, 653 __in uint32_t offset, 654 __in uint32_t length, 655 __in uint32_t end, 656 __out uint32_t *deltap 657 ) 658 { 659 uint32_t move_start = offset + length; 660 uint32_t move_length = end - move_start; 661 662 _NOTE(ARGUNUSED(enp)) 663 EFSYS_ASSERT(end <= buffer_size); 664 665 /* Shift everything after the key down */ 666 memmove(bufferp + offset, bufferp + move_start, move_length); 667 668 *deltap = length; 669 670 return (0); 671 } 672 673 __checkReturn efx_rc_t 674 efx_lic_v1v2_create_partition( 675 __in efx_nic_t *enp, 676 __in_bcount(buffer_size) 677 caddr_t bufferp, 678 __in size_t buffer_size 679 ) 680 { 681 _NOTE(ARGUNUSED(enp)) 682 EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size); 683 684 /* Write terminator */ 685 memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH); 686 return (0); 687 } 688 689 690 __checkReturn efx_rc_t 691 efx_lic_v1v2_finish_partition( 692 __in efx_nic_t *enp, 693 __in_bcount(buffer_size) 694 caddr_t bufferp, 695 __in size_t buffer_size 696 ) 697 { 698 _NOTE(ARGUNUSED(enp, bufferp, buffer_size)) 699 700 return (0); 701 } 702 703 #endif /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */ 704 705 706 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */ 707 708 #if EFSYS_OPT_HUNTINGTON 709 710 static __checkReturn efx_rc_t 711 efx_mcdi_licensed_app_state( 712 __in efx_nic_t *enp, 713 __in uint64_t app_id, 714 __out boolean_t *licensedp) 715 { 716 efx_mcdi_req_t req; 717 uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN, 718 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)]; 719 uint32_t app_state; 720 efx_rc_t rc; 721 722 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); 723 724 /* V2 licensing supports 32bit app id only */ 725 if ((app_id >> 32) != 0) { 726 rc = EINVAL; 727 goto fail1; 728 } 729 730 (void) memset(payload, 0, sizeof (payload)); 731 req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE; 732 req.emr_in_buf = payload; 733 req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN; 734 req.emr_out_buf = payload; 735 req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN; 736 737 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID, 738 app_id & 0xffffffff); 739 740 efx_mcdi_execute(enp, &req); 741 742 if (req.emr_rc != 0) { 743 rc = req.emr_rc; 744 goto fail2; 745 } 746 747 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) { 748 rc = EMSGSIZE; 749 goto fail3; 750 } 751 752 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE)); 753 if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) { 754 *licensedp = B_TRUE; 755 } else { 756 *licensedp = B_FALSE; 757 } 758 759 return (0); 760 761 fail3: 762 EFSYS_PROBE(fail3); 763 fail2: 764 EFSYS_PROBE(fail2); 765 fail1: 766 EFSYS_PROBE1(fail1, efx_rc_t, rc); 767 768 return (rc); 769 } 770 771 static __checkReturn efx_rc_t 772 efx_mcdi_licensing_update_licenses( 773 __in efx_nic_t *enp) 774 { 775 efx_mcdi_req_t req; 776 uint8_t payload[MC_CMD_LICENSING_IN_LEN]; 777 efx_rc_t rc; 778 779 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); 780 781 (void) memset(payload, 0, sizeof (payload)); 782 req.emr_cmd = MC_CMD_LICENSING; 783 req.emr_in_buf = payload; 784 req.emr_in_length = MC_CMD_LICENSING_IN_LEN; 785 req.emr_out_buf = payload; 786 req.emr_out_length = 0; 787 788 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP, 789 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE); 790 791 efx_mcdi_execute(enp, &req); 792 793 if (req.emr_rc != 0) { 794 rc = req.emr_rc; 795 goto fail1; 796 } 797 798 if (req.emr_out_length_used != 0) { 799 rc = EIO; 800 goto fail2; 801 } 802 803 return (0); 804 805 fail2: 806 EFSYS_PROBE(fail2); 807 fail1: 808 EFSYS_PROBE1(fail1, efx_rc_t, rc); 809 810 return (rc); 811 } 812 813 static __checkReturn efx_rc_t 814 efx_mcdi_licensing_get_key_stats( 815 __in efx_nic_t *enp, 816 __out efx_key_stats_t *eksp) 817 { 818 efx_mcdi_req_t req; 819 uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN, 820 MC_CMD_LICENSING_OUT_LEN)]; 821 efx_rc_t rc; 822 823 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); 824 825 (void) memset(payload, 0, sizeof (payload)); 826 req.emr_cmd = MC_CMD_LICENSING; 827 req.emr_in_buf = payload; 828 req.emr_in_length = MC_CMD_LICENSING_IN_LEN; 829 req.emr_out_buf = payload; 830 req.emr_out_length = MC_CMD_LICENSING_OUT_LEN; 831 832 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP, 833 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS); 834 835 efx_mcdi_execute(enp, &req); 836 837 if (req.emr_rc != 0) { 838 rc = req.emr_rc; 839 goto fail1; 840 } 841 842 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) { 843 rc = EMSGSIZE; 844 goto fail2; 845 } 846 847 eksp->eks_valid = 848 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS); 849 eksp->eks_invalid = 850 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS); 851 eksp->eks_blacklisted = 852 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS); 853 eksp->eks_unverifiable = 854 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS); 855 eksp->eks_wrong_node = 856 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS); 857 eksp->eks_licensed_apps_lo = 0; 858 eksp->eks_licensed_apps_hi = 0; 859 eksp->eks_licensed_features_lo = 0; 860 eksp->eks_licensed_features_hi = 0; 861 862 return (0); 863 864 fail2: 865 EFSYS_PROBE(fail2); 866 fail1: 867 EFSYS_PROBE1(fail1, efx_rc_t, rc); 868 869 return (rc); 870 } 871 872 #endif /* EFSYS_OPT_HUNTINGTON */ 873 874 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */ 875 876 #if EFSYS_OPT_MEDFORD 877 878 static __checkReturn efx_rc_t 879 efx_mcdi_licensing_v3_update_licenses( 880 __in efx_nic_t *enp) 881 { 882 efx_mcdi_req_t req; 883 uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN]; 884 efx_rc_t rc; 885 886 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); 887 888 (void) memset(payload, 0, sizeof (payload)); 889 req.emr_cmd = MC_CMD_LICENSING_V3; 890 req.emr_in_buf = payload; 891 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN; 892 req.emr_out_buf = NULL; 893 req.emr_out_length = 0; 894 895 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP, 896 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE); 897 898 efx_mcdi_execute(enp, &req); 899 900 if (req.emr_rc != 0) { 901 rc = req.emr_rc; 902 goto fail1; 903 } 904 905 return (0); 906 907 fail1: 908 EFSYS_PROBE1(fail1, efx_rc_t, rc); 909 910 return (rc); 911 } 912 913 static __checkReturn efx_rc_t 914 efx_mcdi_licensing_v3_report_license( 915 __in efx_nic_t *enp, 916 __out efx_key_stats_t *eksp) 917 { 918 efx_mcdi_req_t req; 919 uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN, 920 MC_CMD_LICENSING_V3_OUT_LEN)]; 921 efx_rc_t rc; 922 923 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); 924 925 (void) memset(payload, 0, sizeof (payload)); 926 req.emr_cmd = MC_CMD_LICENSING_V3; 927 req.emr_in_buf = payload; 928 req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN; 929 req.emr_out_buf = payload; 930 req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN; 931 932 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP, 933 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE); 934 935 efx_mcdi_execute_quiet(enp, &req); 936 937 if (req.emr_rc != 0) { 938 rc = req.emr_rc; 939 goto fail1; 940 } 941 942 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) { 943 rc = EMSGSIZE; 944 goto fail2; 945 } 946 947 eksp->eks_valid = 948 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS); 949 eksp->eks_invalid = 950 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS); 951 eksp->eks_blacklisted = 0; 952 eksp->eks_unverifiable = 953 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS); 954 eksp->eks_wrong_node = 955 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS); 956 eksp->eks_licensed_apps_lo = 957 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO); 958 eksp->eks_licensed_apps_hi = 959 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI); 960 eksp->eks_licensed_features_lo = 961 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO); 962 eksp->eks_licensed_features_hi = 963 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI); 964 965 return (0); 966 967 fail2: 968 EFSYS_PROBE(fail2); 969 fail1: 970 EFSYS_PROBE1(fail1, efx_rc_t, rc); 971 972 return (rc); 973 } 974 975 static __checkReturn efx_rc_t 976 efx_mcdi_licensing_v3_app_state( 977 __in efx_nic_t *enp, 978 __in uint64_t app_id, 979 __out boolean_t *licensedp) 980 { 981 efx_mcdi_req_t req; 982 uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN, 983 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)]; 984 uint32_t app_state; 985 efx_rc_t rc; 986 987 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); 988 989 (void) memset(payload, 0, sizeof (payload)); 990 req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE; 991 req.emr_in_buf = payload; 992 req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN; 993 req.emr_out_buf = payload; 994 req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN; 995 996 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO, 997 app_id & 0xffffffff); 998 MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI, 999 app_id >> 32); 1000 1001 efx_mcdi_execute(enp, &req); 1002 1003 if (req.emr_rc != 0) { 1004 rc = req.emr_rc; 1005 goto fail1; 1006 } 1007 1008 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) { 1009 rc = EMSGSIZE; 1010 goto fail2; 1011 } 1012 1013 app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE)); 1014 if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) { 1015 *licensedp = B_TRUE; 1016 } else { 1017 *licensedp = B_FALSE; 1018 } 1019 1020 return (0); 1021 1022 fail2: 1023 EFSYS_PROBE(fail2); 1024 fail1: 1025 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1026 1027 return (rc); 1028 } 1029 1030 static __checkReturn efx_rc_t 1031 efx_mcdi_licensing_v3_get_id( 1032 __in efx_nic_t *enp, 1033 __in size_t buffer_size, 1034 __out uint32_t *typep, 1035 __out size_t *lengthp, 1036 __out_bcount_part_opt(buffer_size, *lengthp) 1037 uint8_t *bufferp) 1038 { 1039 efx_mcdi_req_t req; 1040 uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN, 1041 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)]; 1042 efx_rc_t rc; 1043 1044 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3; 1045 1046 if (bufferp == NULL) { 1047 /* Request id type and length only */ 1048 req.emr_in_buf = bufferp; 1049 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN; 1050 req.emr_out_buf = bufferp; 1051 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN; 1052 (void) memset(payload, 0, sizeof (payload)); 1053 } else { 1054 /* Request full buffer */ 1055 req.emr_in_buf = bufferp; 1056 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN; 1057 req.emr_out_buf = bufferp; 1058 req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX); 1059 (void) memset(bufferp, 0, req.emr_out_length); 1060 } 1061 1062 efx_mcdi_execute_quiet(enp, &req); 1063 1064 if (req.emr_rc != 0) { 1065 rc = req.emr_rc; 1066 goto fail1; 1067 } 1068 1069 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) { 1070 rc = EMSGSIZE; 1071 goto fail2; 1072 } 1073 1074 *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE); 1075 *lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH); 1076 1077 if (bufferp == NULL) { 1078 /* modify length requirements to indicate to caller the extra buffering 1079 ** needed to read the complete output. 1080 */ 1081 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN; 1082 } else { 1083 /* Shift ID down to start of buffer */ 1084 memmove(bufferp, 1085 bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST, 1086 *lengthp); 1087 memset(bufferp + (*lengthp), 0, 1088 MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST); 1089 } 1090 1091 return (0); 1092 1093 fail2: 1094 EFSYS_PROBE(fail2); 1095 fail1: 1096 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1097 1098 return (rc); 1099 } 1100 1101 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */ 1102 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64) 1103 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160) 1104 1105 __checkReturn efx_rc_t 1106 efx_lic_v3_find_start( 1107 __in efx_nic_t *enp, 1108 __in_bcount(buffer_size) 1109 caddr_t bufferp, 1110 __in size_t buffer_size, 1111 __out uint32_t *startp 1112 ) 1113 { 1114 _NOTE(ARGUNUSED(enp)) 1115 1116 return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp); 1117 } 1118 1119 __checkReturn efx_rc_t 1120 efx_lic_v3_find_end( 1121 __in efx_nic_t *enp, 1122 __in_bcount(buffer_size) 1123 caddr_t bufferp, 1124 __in size_t buffer_size, 1125 __in uint32_t offset, 1126 __out uint32_t *endp 1127 ) 1128 { 1129 _NOTE(ARGUNUSED(enp)) 1130 1131 return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp); 1132 } 1133 1134 __checkReturn __success(return != B_FALSE) boolean_t 1135 efx_lic_v3_find_key( 1136 __in efx_nic_t *enp, 1137 __in_bcount(buffer_size) 1138 caddr_t bufferp, 1139 __in size_t buffer_size, 1140 __in uint32_t offset, 1141 __out uint32_t *startp, 1142 __out uint32_t *lengthp 1143 ) 1144 { 1145 _NOTE(ARGUNUSED(enp)) 1146 1147 return ef10_nvram_buffer_find_item(bufferp, buffer_size, 1148 offset, startp, lengthp); 1149 } 1150 1151 __checkReturn __success(return != B_FALSE) boolean_t 1152 efx_lic_v3_validate_key( 1153 __in efx_nic_t *enp, 1154 __in_bcount(length) caddr_t keyp, 1155 __in uint32_t length 1156 ) 1157 { 1158 /* Check key is a valid V3 key */ 1159 uint8_t key_type; 1160 uint8_t key_length; 1161 1162 _NOTE(ARGUNUSED(enp)) 1163 1164 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) { 1165 goto fail1; 1166 } 1167 1168 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) { 1169 goto fail2; 1170 } 1171 1172 key_type = ((uint8_t *)keyp)[0]; 1173 key_length = ((uint8_t *)keyp)[1]; 1174 1175 if (key_type < 3) { 1176 goto fail3; 1177 } 1178 if (key_length > length) { 1179 goto fail4; 1180 } 1181 return (B_TRUE); 1182 1183 fail4: 1184 EFSYS_PROBE(fail4); 1185 fail3: 1186 EFSYS_PROBE(fail3); 1187 fail2: 1188 EFSYS_PROBE(fail2); 1189 fail1: 1190 EFSYS_PROBE(fail1); 1191 1192 return (B_FALSE); 1193 } 1194 1195 __checkReturn efx_rc_t 1196 efx_lic_v3_read_key( 1197 __in efx_nic_t *enp, 1198 __in_bcount(buffer_size) 1199 caddr_t bufferp, 1200 __in size_t buffer_size, 1201 __in uint32_t offset, 1202 __in uint32_t length, 1203 __out_bcount_part(key_max_size, *lengthp) 1204 caddr_t keyp, 1205 __in size_t key_max_size, 1206 __out uint32_t *lengthp 1207 ) 1208 { 1209 _NOTE(ARGUNUSED(enp)) 1210 1211 return ef10_nvram_buffer_get_item(bufferp, buffer_size, 1212 offset, length, keyp, key_max_size, lengthp); 1213 } 1214 1215 __checkReturn efx_rc_t 1216 efx_lic_v3_write_key( 1217 __in efx_nic_t *enp, 1218 __in_bcount(buffer_size) 1219 caddr_t bufferp, 1220 __in size_t buffer_size, 1221 __in uint32_t offset, 1222 __in_bcount(length) caddr_t keyp, 1223 __in uint32_t length, 1224 __out uint32_t *lengthp 1225 ) 1226 { 1227 _NOTE(ARGUNUSED(enp)) 1228 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX); 1229 1230 return ef10_nvram_buffer_insert_item(bufferp, buffer_size, 1231 offset, keyp, length, lengthp); 1232 } 1233 1234 __checkReturn efx_rc_t 1235 efx_lic_v3_delete_key( 1236 __in efx_nic_t *enp, 1237 __in_bcount(buffer_size) 1238 caddr_t bufferp, 1239 __in size_t buffer_size, 1240 __in uint32_t offset, 1241 __in uint32_t length, 1242 __in uint32_t end, 1243 __out uint32_t *deltap 1244 ) 1245 { 1246 efx_rc_t rc; 1247 1248 _NOTE(ARGUNUSED(enp)) 1249 1250 if ((rc = ef10_nvram_buffer_delete_item(bufferp, 1251 buffer_size, offset, length, end)) != 0) { 1252 goto fail1; 1253 } 1254 1255 *deltap = length; 1256 1257 return (0); 1258 1259 fail1: 1260 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1261 1262 return (rc); 1263 } 1264 1265 __checkReturn efx_rc_t 1266 efx_lic_v3_create_partition( 1267 __in efx_nic_t *enp, 1268 __in_bcount(buffer_size) 1269 caddr_t bufferp, 1270 __in size_t buffer_size 1271 ) 1272 { 1273 efx_rc_t rc; 1274 1275 /* Construct empty partition */ 1276 if ((rc = ef10_nvram_buffer_create(enp, 1277 NVRAM_PARTITION_TYPE_LICENSE, 1278 bufferp, buffer_size)) != 0) { 1279 rc = EFAULT; 1280 goto fail1; 1281 } 1282 1283 return (0); 1284 1285 fail1: 1286 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1287 1288 return (rc); 1289 } 1290 1291 __checkReturn efx_rc_t 1292 efx_lic_v3_finish_partition( 1293 __in efx_nic_t *enp, 1294 __in_bcount(buffer_size) 1295 caddr_t bufferp, 1296 __in size_t buffer_size 1297 ) 1298 { 1299 efx_rc_t rc; 1300 1301 if ((rc = ef10_nvram_buffer_finish(bufferp, 1302 buffer_size)) != 0) { 1303 goto fail1; 1304 } 1305 1306 /* Validate completed partition */ 1307 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE, 1308 bufferp, buffer_size)) != 0) { 1309 goto fail2; 1310 } 1311 1312 return (0); 1313 1314 fail2: 1315 EFSYS_PROBE(fail2); 1316 fail1: 1317 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1318 1319 return (rc); 1320 } 1321 1322 1323 #endif /* EFSYS_OPT_MEDFORD */ 1324 1325 __checkReturn efx_rc_t 1326 efx_lic_init( 1327 __in efx_nic_t *enp) 1328 { 1329 const efx_lic_ops_t *elop; 1330 efx_key_stats_t eks; 1331 efx_rc_t rc; 1332 1333 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1334 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1335 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC)); 1336 1337 switch (enp->en_family) { 1338 1339 #if EFSYS_OPT_SIENA 1340 case EFX_FAMILY_SIENA: 1341 elop = &__efx_lic_v1_ops; 1342 break; 1343 #endif /* EFSYS_OPT_SIENA */ 1344 1345 #if EFSYS_OPT_HUNTINGTON 1346 case EFX_FAMILY_HUNTINGTON: 1347 elop = &__efx_lic_v2_ops; 1348 break; 1349 #endif /* EFSYS_OPT_HUNTINGTON */ 1350 1351 #if EFSYS_OPT_MEDFORD 1352 case EFX_FAMILY_MEDFORD: 1353 elop = &__efx_lic_v3_ops; 1354 break; 1355 #endif /* EFSYS_OPT_MEDFORD */ 1356 1357 default: 1358 EFSYS_ASSERT(0); 1359 rc = ENOTSUP; 1360 goto fail1; 1361 } 1362 1363 enp->en_elop = elop; 1364 enp->en_mod_flags |= EFX_MOD_LIC; 1365 1366 /* Probe for support */ 1367 if (efx_lic_get_key_stats(enp, &eks) == 0) { 1368 enp->en_licensing_supported = B_TRUE; 1369 } else { 1370 enp->en_licensing_supported = B_FALSE; 1371 } 1372 1373 return (0); 1374 1375 fail1: 1376 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1377 1378 return (rc); 1379 } 1380 1381 extern __checkReturn boolean_t 1382 efx_lic_check_support( 1383 __in efx_nic_t *enp) 1384 { 1385 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1386 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1387 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1388 1389 return enp->en_licensing_supported; 1390 } 1391 1392 void 1393 efx_lic_fini( 1394 __in efx_nic_t *enp) 1395 { 1396 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1397 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1398 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1399 1400 enp->en_elop = NULL; 1401 enp->en_mod_flags &= ~EFX_MOD_LIC; 1402 } 1403 1404 1405 __checkReturn efx_rc_t 1406 efx_lic_update_licenses( 1407 __in efx_nic_t *enp) 1408 { 1409 const efx_lic_ops_t *elop = enp->en_elop; 1410 efx_rc_t rc; 1411 1412 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1413 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1414 1415 if ((rc = elop->elo_update_licenses(enp)) != 0) 1416 goto fail1; 1417 1418 return (0); 1419 1420 fail1: 1421 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1422 1423 return (rc); 1424 } 1425 1426 __checkReturn efx_rc_t 1427 efx_lic_get_key_stats( 1428 __in efx_nic_t *enp, 1429 __out efx_key_stats_t *eksp) 1430 { 1431 const efx_lic_ops_t *elop = enp->en_elop; 1432 efx_rc_t rc; 1433 1434 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1435 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1436 1437 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0) 1438 goto fail1; 1439 1440 return (0); 1441 1442 fail1: 1443 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1444 1445 return (rc); 1446 } 1447 1448 __checkReturn efx_rc_t 1449 efx_lic_app_state( 1450 __in efx_nic_t *enp, 1451 __in uint64_t app_id, 1452 __out boolean_t *licensedp) 1453 { 1454 const efx_lic_ops_t *elop = enp->en_elop; 1455 efx_rc_t rc; 1456 1457 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1458 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1459 1460 if (elop->elo_app_state == NULL) 1461 return (ENOTSUP); 1462 1463 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0) 1464 goto fail1; 1465 1466 return (0); 1467 1468 fail1: 1469 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1470 1471 return (rc); 1472 } 1473 1474 __checkReturn efx_rc_t 1475 efx_lic_get_id( 1476 __in efx_nic_t *enp, 1477 __in size_t buffer_size, 1478 __out uint32_t *typep, 1479 __out size_t *lengthp, 1480 __out_opt uint8_t *bufferp 1481 ) 1482 { 1483 const efx_lic_ops_t *elop = enp->en_elop; 1484 efx_rc_t rc; 1485 1486 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1487 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1488 1489 if (elop->elo_get_id == NULL) 1490 return (ENOTSUP); 1491 1492 if ((rc = elop->elo_get_id(enp, buffer_size, typep, 1493 lengthp, bufferp)) != 0) 1494 goto fail1; 1495 1496 return (0); 1497 1498 fail1: 1499 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1500 1501 return (rc); 1502 } 1503 1504 /* Buffer management API - abstracts varying TLV format used for License partition */ 1505 1506 __checkReturn efx_rc_t 1507 efx_lic_find_start( 1508 __in efx_nic_t *enp, 1509 __in_bcount(buffer_size) 1510 caddr_t bufferp, 1511 __in size_t buffer_size, 1512 __out uint32_t *startp 1513 ) 1514 { 1515 const efx_lic_ops_t *elop = enp->en_elop; 1516 efx_rc_t rc; 1517 1518 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1519 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1520 1521 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0) 1522 goto fail1; 1523 1524 return (0); 1525 1526 fail1: 1527 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1528 1529 return (rc); 1530 } 1531 1532 __checkReturn efx_rc_t 1533 efx_lic_find_end( 1534 __in efx_nic_t *enp, 1535 __in_bcount(buffer_size) 1536 caddr_t bufferp, 1537 __in size_t buffer_size, 1538 __in uint32_t offset, 1539 __out uint32_t *endp 1540 ) 1541 { 1542 const efx_lic_ops_t *elop = enp->en_elop; 1543 efx_rc_t rc; 1544 1545 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1546 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1547 1548 if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0) 1549 goto fail1; 1550 1551 return (0); 1552 1553 fail1: 1554 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1555 1556 return (rc); 1557 } 1558 1559 __checkReturn __success(return != B_FALSE) boolean_t 1560 efx_lic_find_key( 1561 __in efx_nic_t *enp, 1562 __in_bcount(buffer_size) 1563 caddr_t bufferp, 1564 __in size_t buffer_size, 1565 __in uint32_t offset, 1566 __out uint32_t *startp, 1567 __out uint32_t *lengthp 1568 ) 1569 { 1570 const efx_lic_ops_t *elop = enp->en_elop; 1571 1572 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1573 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1574 1575 EFSYS_ASSERT(bufferp); 1576 EFSYS_ASSERT(startp); 1577 EFSYS_ASSERT(lengthp); 1578 1579 return (elop->elo_find_key(enp, bufferp, buffer_size, offset, 1580 startp, lengthp)); 1581 } 1582 1583 1584 /* Validate that the buffer contains a single key in a recognised format. 1585 ** An empty or terminator buffer is not accepted as a valid key. 1586 */ 1587 __checkReturn __success(return != B_FALSE) boolean_t 1588 efx_lic_validate_key( 1589 __in efx_nic_t *enp, 1590 __in_bcount(length) caddr_t keyp, 1591 __in uint32_t length 1592 ) 1593 { 1594 const efx_lic_ops_t *elop = enp->en_elop; 1595 boolean_t rc; 1596 1597 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1598 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1599 1600 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE) 1601 goto fail1; 1602 1603 return (B_TRUE); 1604 1605 fail1: 1606 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1607 1608 return (rc); 1609 } 1610 1611 __checkReturn efx_rc_t 1612 efx_lic_read_key( 1613 __in efx_nic_t *enp, 1614 __in_bcount(buffer_size) 1615 caddr_t bufferp, 1616 __in size_t buffer_size, 1617 __in uint32_t offset, 1618 __in uint32_t length, 1619 __out_bcount_part(key_max_size, *lengthp) 1620 caddr_t keyp, 1621 __in size_t key_max_size, 1622 __out uint32_t *lengthp 1623 ) 1624 { 1625 const efx_lic_ops_t *elop = enp->en_elop; 1626 efx_rc_t rc; 1627 1628 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1629 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1630 1631 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset, 1632 length, keyp, key_max_size, lengthp)) != 0) 1633 goto fail1; 1634 1635 return (0); 1636 1637 fail1: 1638 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1639 1640 return (rc); 1641 } 1642 1643 __checkReturn efx_rc_t 1644 efx_lic_write_key( 1645 __in efx_nic_t *enp, 1646 __in_bcount(buffer_size) 1647 caddr_t bufferp, 1648 __in size_t buffer_size, 1649 __in uint32_t offset, 1650 __in_bcount(length) caddr_t keyp, 1651 __in uint32_t length, 1652 __out uint32_t *lengthp 1653 ) 1654 { 1655 const efx_lic_ops_t *elop = enp->en_elop; 1656 efx_rc_t rc; 1657 1658 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1659 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1660 1661 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset, 1662 keyp, length, lengthp)) != 0) 1663 goto fail1; 1664 1665 return (0); 1666 1667 fail1: 1668 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1669 1670 return (rc); 1671 } 1672 1673 __checkReturn efx_rc_t 1674 efx_lic_delete_key( 1675 __in efx_nic_t *enp, 1676 __in_bcount(buffer_size) 1677 caddr_t bufferp, 1678 __in size_t buffer_size, 1679 __in uint32_t offset, 1680 __in uint32_t length, 1681 __in uint32_t end, 1682 __out uint32_t *deltap 1683 ) 1684 { 1685 const efx_lic_ops_t *elop = enp->en_elop; 1686 efx_rc_t rc; 1687 1688 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1689 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1690 1691 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset, 1692 length, end, deltap)) != 0) 1693 goto fail1; 1694 1695 return (0); 1696 1697 fail1: 1698 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1699 1700 return (rc); 1701 } 1702 1703 __checkReturn efx_rc_t 1704 efx_lic_create_partition( 1705 __in efx_nic_t *enp, 1706 __in_bcount(buffer_size) 1707 caddr_t bufferp, 1708 __in size_t buffer_size 1709 ) 1710 { 1711 const efx_lic_ops_t *elop = enp->en_elop; 1712 efx_rc_t rc; 1713 1714 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1715 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1716 1717 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0) 1718 goto fail1; 1719 1720 return (0); 1721 1722 fail1: 1723 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1724 1725 return (rc); 1726 } 1727 1728 1729 __checkReturn efx_rc_t 1730 efx_lic_finish_partition( 1731 __in efx_nic_t *enp, 1732 __in_bcount(buffer_size) 1733 caddr_t bufferp, 1734 __in size_t buffer_size 1735 ) 1736 { 1737 const efx_lic_ops_t *elop = enp->en_elop; 1738 efx_rc_t rc; 1739 1740 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1741 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1742 1743 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0) 1744 goto fail1; 1745 1746 return (0); 1747 1748 fail1: 1749 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1750 1751 return (rc); 1752 } 1753 1754 #endif /* EFSYS_OPT_LICENSING */ 1755