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, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST); 1088 } 1089 1090 return (0); 1091 1092 fail2: 1093 EFSYS_PROBE(fail2); 1094 fail1: 1095 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1096 1097 return (rc); 1098 } 1099 1100 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */ 1101 #define EFX_LICENSE_V3_KEY_LENGTH_MIN (64) 1102 #define EFX_LICENSE_V3_KEY_LENGTH_MAX (160) 1103 1104 __checkReturn efx_rc_t 1105 efx_lic_v3_find_start( 1106 __in efx_nic_t *enp, 1107 __in_bcount(buffer_size) 1108 caddr_t bufferp, 1109 __in size_t buffer_size, 1110 __out uint32_t *startp 1111 ) 1112 { 1113 _NOTE(ARGUNUSED(enp)) 1114 1115 return ef10_nvram_buffer_find_item_start(bufferp, buffer_size, startp); 1116 } 1117 1118 __checkReturn efx_rc_t 1119 efx_lic_v3_find_end( 1120 __in efx_nic_t *enp, 1121 __in_bcount(buffer_size) 1122 caddr_t bufferp, 1123 __in size_t buffer_size, 1124 __in uint32_t offset, 1125 __out uint32_t *endp 1126 ) 1127 { 1128 _NOTE(ARGUNUSED(enp)) 1129 1130 return ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp); 1131 } 1132 1133 __checkReturn __success(return != B_FALSE) boolean_t 1134 efx_lic_v3_find_key( 1135 __in efx_nic_t *enp, 1136 __in_bcount(buffer_size) 1137 caddr_t bufferp, 1138 __in size_t buffer_size, 1139 __in uint32_t offset, 1140 __out uint32_t *startp, 1141 __out uint32_t *lengthp 1142 ) 1143 { 1144 _NOTE(ARGUNUSED(enp)) 1145 1146 return ef10_nvram_buffer_find_item(bufferp, buffer_size, 1147 offset, startp, lengthp); 1148 } 1149 1150 __checkReturn __success(return != B_FALSE) boolean_t 1151 efx_lic_v3_validate_key( 1152 __in efx_nic_t *enp, 1153 __in_bcount(length) caddr_t keyp, 1154 __in uint32_t length 1155 ) 1156 { 1157 // Check key is a valid V3 key 1158 uint8_t key_type; 1159 uint8_t key_length; 1160 1161 _NOTE(ARGUNUSED(enp)) 1162 1163 if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) { 1164 goto fail1; 1165 } 1166 1167 if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) { 1168 goto fail2; 1169 } 1170 1171 key_type = ((uint8_t*)keyp)[0]; 1172 key_length = ((uint8_t*)keyp)[1]; 1173 1174 if (key_type < 3) { 1175 goto fail3; 1176 } 1177 if (key_length > length) { 1178 goto fail4; 1179 } 1180 return (B_TRUE); 1181 1182 fail4: 1183 EFSYS_PROBE(fail4); 1184 fail3: 1185 EFSYS_PROBE(fail3); 1186 fail2: 1187 EFSYS_PROBE(fail2); 1188 fail1: 1189 EFSYS_PROBE(fail1); 1190 1191 return (B_FALSE); 1192 } 1193 1194 __checkReturn efx_rc_t 1195 efx_lic_v3_read_key( 1196 __in efx_nic_t *enp, 1197 __in_bcount(buffer_size) 1198 caddr_t bufferp, 1199 __in size_t buffer_size, 1200 __in uint32_t offset, 1201 __in uint32_t length, 1202 __out_bcount_part(key_max_size, *lengthp) 1203 caddr_t keyp, 1204 __in size_t key_max_size, 1205 __out uint32_t *lengthp 1206 ) 1207 { 1208 _NOTE(ARGUNUSED(enp)) 1209 1210 return ef10_nvram_buffer_get_item(bufferp, buffer_size, 1211 offset, length, keyp, key_max_size, lengthp); 1212 } 1213 1214 __checkReturn efx_rc_t 1215 efx_lic_v3_write_key( 1216 __in efx_nic_t *enp, 1217 __in_bcount(buffer_size) 1218 caddr_t bufferp, 1219 __in size_t buffer_size, 1220 __in uint32_t offset, 1221 __in_bcount(length) caddr_t keyp, 1222 __in uint32_t length, 1223 __out uint32_t *lengthp 1224 ) 1225 { 1226 _NOTE(ARGUNUSED(enp)) 1227 EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX); 1228 1229 return ef10_nvram_buffer_insert_item(bufferp, buffer_size, 1230 offset, keyp, length, lengthp); 1231 } 1232 1233 __checkReturn efx_rc_t 1234 efx_lic_v3_delete_key( 1235 __in efx_nic_t *enp, 1236 __in_bcount(buffer_size) 1237 caddr_t bufferp, 1238 __in size_t buffer_size, 1239 __in uint32_t offset, 1240 __in uint32_t length, 1241 __in uint32_t end, 1242 __out uint32_t *deltap 1243 ) 1244 { 1245 efx_rc_t rc; 1246 1247 _NOTE(ARGUNUSED(enp)) 1248 1249 if ((rc = ef10_nvram_buffer_delete_item(bufferp, 1250 buffer_size, offset, length, end)) != 0) { 1251 goto fail1; 1252 } 1253 1254 *deltap = length; 1255 1256 return (0); 1257 1258 fail1: 1259 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1260 1261 return (rc); 1262 } 1263 1264 __checkReturn efx_rc_t 1265 efx_lic_v3_create_partition( 1266 __in efx_nic_t *enp, 1267 __in_bcount(buffer_size) 1268 caddr_t bufferp, 1269 __in size_t buffer_size 1270 ) 1271 { 1272 efx_rc_t rc; 1273 1274 // Construct empty partition 1275 if ((rc = ef10_nvram_buffer_create(enp, 1276 NVRAM_PARTITION_TYPE_LICENSE, 1277 bufferp, buffer_size)) != 0) { 1278 rc = EFAULT; 1279 goto fail1; 1280 } 1281 1282 return (0); 1283 1284 fail1: 1285 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1286 1287 return (rc); 1288 } 1289 1290 __checkReturn efx_rc_t 1291 efx_lic_v3_finish_partition( 1292 __in efx_nic_t *enp, 1293 __in_bcount(buffer_size) 1294 caddr_t bufferp, 1295 __in size_t buffer_size 1296 ) 1297 { 1298 efx_rc_t rc; 1299 1300 if ((rc = ef10_nvram_buffer_finish(bufferp, 1301 buffer_size)) != 0) { 1302 goto fail1; 1303 } 1304 1305 // Validate completed partition 1306 if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE, 1307 bufferp, buffer_size)) != 0) { 1308 goto fail2; 1309 } 1310 1311 return (0); 1312 1313 fail2: 1314 EFSYS_PROBE(fail2); 1315 fail1: 1316 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1317 1318 return (rc); 1319 } 1320 1321 1322 #endif /* EFSYS_OPT_MEDFORD */ 1323 1324 __checkReturn efx_rc_t 1325 efx_lic_init( 1326 __in efx_nic_t *enp) 1327 { 1328 const efx_lic_ops_t *elop; 1329 efx_key_stats_t eks; 1330 efx_rc_t rc; 1331 1332 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1333 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1334 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC)); 1335 1336 switch (enp->en_family) { 1337 1338 #if EFSYS_OPT_SIENA 1339 case EFX_FAMILY_SIENA: 1340 elop = &__efx_lic_v1_ops; 1341 break; 1342 #endif /* EFSYS_OPT_SIENA */ 1343 1344 #if EFSYS_OPT_HUNTINGTON 1345 case EFX_FAMILY_HUNTINGTON: 1346 elop = &__efx_lic_v2_ops; 1347 break; 1348 #endif /* EFSYS_OPT_HUNTINGTON */ 1349 1350 #if EFSYS_OPT_MEDFORD 1351 case EFX_FAMILY_MEDFORD: 1352 elop = &__efx_lic_v3_ops; 1353 break; 1354 #endif /* EFSYS_OPT_MEDFORD */ 1355 1356 default: 1357 EFSYS_ASSERT(0); 1358 rc = ENOTSUP; 1359 goto fail1; 1360 } 1361 1362 enp->en_elop = elop; 1363 enp->en_mod_flags |= EFX_MOD_LIC; 1364 1365 /* Probe for support */ 1366 if (efx_lic_get_key_stats(enp, &eks) == 0) { 1367 enp->en_licensing_supported = B_TRUE; 1368 } else { 1369 enp->en_licensing_supported = B_FALSE; 1370 } 1371 1372 return (0); 1373 1374 fail1: 1375 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1376 1377 return (rc); 1378 } 1379 1380 extern __checkReturn boolean_t 1381 efx_lic_check_support( 1382 __in efx_nic_t *enp) 1383 { 1384 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1385 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1386 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1387 1388 return enp->en_licensing_supported; 1389 } 1390 1391 void 1392 efx_lic_fini( 1393 __in efx_nic_t *enp) 1394 { 1395 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1396 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1397 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1398 1399 enp->en_elop = NULL; 1400 enp->en_mod_flags &= ~EFX_MOD_LIC; 1401 } 1402 1403 1404 __checkReturn efx_rc_t 1405 efx_lic_update_licenses( 1406 __in efx_nic_t *enp) 1407 { 1408 const efx_lic_ops_t *elop = enp->en_elop; 1409 efx_rc_t rc; 1410 1411 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1412 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1413 1414 if ((rc = elop->elo_update_licenses(enp)) != 0) 1415 goto fail1; 1416 1417 return (0); 1418 1419 fail1: 1420 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1421 1422 return (rc); 1423 } 1424 1425 __checkReturn efx_rc_t 1426 efx_lic_get_key_stats( 1427 __in efx_nic_t *enp, 1428 __out efx_key_stats_t *eksp) 1429 { 1430 const efx_lic_ops_t *elop = enp->en_elop; 1431 efx_rc_t rc; 1432 1433 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1434 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1435 1436 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0) 1437 goto fail1; 1438 1439 return (0); 1440 1441 fail1: 1442 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1443 1444 return (rc); 1445 } 1446 1447 __checkReturn efx_rc_t 1448 efx_lic_app_state( 1449 __in efx_nic_t *enp, 1450 __in uint64_t app_id, 1451 __out boolean_t *licensedp) 1452 { 1453 const efx_lic_ops_t *elop = enp->en_elop; 1454 efx_rc_t rc; 1455 1456 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1457 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1458 1459 if (elop->elo_app_state == NULL) 1460 return (ENOTSUP); 1461 1462 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0) 1463 goto fail1; 1464 1465 return (0); 1466 1467 fail1: 1468 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1469 1470 return (rc); 1471 } 1472 1473 __checkReturn efx_rc_t 1474 efx_lic_get_id( 1475 __in efx_nic_t *enp, 1476 __in size_t buffer_size, 1477 __out uint32_t *typep, 1478 __out size_t *lengthp, 1479 __out_opt uint8_t *bufferp 1480 ) 1481 { 1482 const efx_lic_ops_t *elop = enp->en_elop; 1483 efx_rc_t rc; 1484 1485 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1486 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1487 1488 if (elop->elo_get_id == NULL) 1489 return (ENOTSUP); 1490 1491 if ((rc = elop->elo_get_id(enp, buffer_size, typep, 1492 lengthp, bufferp)) != 0) 1493 goto fail1; 1494 1495 return (0); 1496 1497 fail1: 1498 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1499 1500 return (rc); 1501 } 1502 1503 /* Buffer management API - abstracts varying TLV format used for License partition */ 1504 1505 __checkReturn efx_rc_t 1506 efx_lic_find_start( 1507 __in efx_nic_t *enp, 1508 __in_bcount(buffer_size) 1509 caddr_t bufferp, 1510 __in size_t buffer_size, 1511 __out uint32_t *startp 1512 ) 1513 { 1514 const efx_lic_ops_t *elop = enp->en_elop; 1515 efx_rc_t rc; 1516 1517 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1518 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1519 1520 if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0) 1521 goto fail1; 1522 1523 return (0); 1524 1525 fail1: 1526 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1527 1528 return (rc); 1529 } 1530 1531 __checkReturn efx_rc_t 1532 efx_lic_find_end( 1533 __in efx_nic_t *enp, 1534 __in_bcount(buffer_size) 1535 caddr_t bufferp, 1536 __in size_t buffer_size, 1537 __in uint32_t offset, 1538 __out uint32_t *endp 1539 ) 1540 { 1541 const efx_lic_ops_t *elop = enp->en_elop; 1542 efx_rc_t rc; 1543 1544 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1545 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1546 1547 if ((rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp)) != 0) 1548 goto fail1; 1549 1550 return (0); 1551 1552 fail1: 1553 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1554 1555 return (rc); 1556 } 1557 1558 __checkReturn __success(return != B_FALSE) boolean_t 1559 efx_lic_find_key( 1560 __in efx_nic_t *enp, 1561 __in_bcount(buffer_size) 1562 caddr_t bufferp, 1563 __in size_t buffer_size, 1564 __in uint32_t offset, 1565 __out uint32_t *startp, 1566 __out uint32_t *lengthp 1567 ) 1568 { 1569 const efx_lic_ops_t *elop = enp->en_elop; 1570 1571 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1572 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1573 1574 EFSYS_ASSERT(bufferp); 1575 EFSYS_ASSERT(startp); 1576 EFSYS_ASSERT(lengthp); 1577 1578 return (elop->elo_find_key(enp, bufferp, buffer_size, offset, 1579 startp, lengthp)); 1580 } 1581 1582 1583 /* Validate that the buffer contains a single key in a recognised format. 1584 ** An empty or terminator buffer is not accepted as a valid key. 1585 */ 1586 __checkReturn __success(return != B_FALSE) boolean_t 1587 efx_lic_validate_key( 1588 __in efx_nic_t *enp, 1589 __in_bcount(length) caddr_t keyp, 1590 __in uint32_t length 1591 ) 1592 { 1593 const efx_lic_ops_t *elop = enp->en_elop; 1594 boolean_t rc; 1595 1596 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1597 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1598 1599 if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE) 1600 goto fail1; 1601 1602 return (B_TRUE); 1603 1604 fail1: 1605 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1606 1607 return (rc); 1608 } 1609 1610 __checkReturn efx_rc_t 1611 efx_lic_read_key( 1612 __in efx_nic_t *enp, 1613 __in_bcount(buffer_size) 1614 caddr_t bufferp, 1615 __in size_t buffer_size, 1616 __in uint32_t offset, 1617 __in uint32_t length, 1618 __out_bcount_part(key_max_size, *lengthp) 1619 caddr_t keyp, 1620 __in size_t key_max_size, 1621 __out uint32_t *lengthp 1622 ) 1623 { 1624 const efx_lic_ops_t *elop = enp->en_elop; 1625 efx_rc_t rc; 1626 1627 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1628 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1629 1630 if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset, 1631 length, keyp, key_max_size, lengthp)) != 0) 1632 goto fail1; 1633 1634 return (0); 1635 1636 fail1: 1637 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1638 1639 return (rc); 1640 } 1641 1642 __checkReturn efx_rc_t 1643 efx_lic_write_key( 1644 __in efx_nic_t *enp, 1645 __in_bcount(buffer_size) 1646 caddr_t bufferp, 1647 __in size_t buffer_size, 1648 __in uint32_t offset, 1649 __in_bcount(length) caddr_t keyp, 1650 __in uint32_t length, 1651 __out uint32_t *lengthp 1652 ) 1653 { 1654 const efx_lic_ops_t *elop = enp->en_elop; 1655 efx_rc_t rc; 1656 1657 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1658 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1659 1660 if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset, 1661 keyp, length, lengthp)) != 0) 1662 goto fail1; 1663 1664 return (0); 1665 1666 fail1: 1667 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1668 1669 return (rc); 1670 } 1671 1672 __checkReturn efx_rc_t 1673 efx_lic_delete_key( 1674 __in efx_nic_t *enp, 1675 __in_bcount(buffer_size) 1676 caddr_t bufferp, 1677 __in size_t buffer_size, 1678 __in uint32_t offset, 1679 __in uint32_t length, 1680 __in uint32_t end, 1681 __out uint32_t *deltap 1682 ) 1683 { 1684 const efx_lic_ops_t *elop = enp->en_elop; 1685 efx_rc_t rc; 1686 1687 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1688 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1689 1690 if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset, 1691 length, end, deltap)) != 0) 1692 goto fail1; 1693 1694 return (0); 1695 1696 fail1: 1697 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1698 1699 return (rc); 1700 } 1701 1702 __checkReturn efx_rc_t 1703 efx_lic_create_partition( 1704 __in efx_nic_t *enp, 1705 __in_bcount(buffer_size) 1706 caddr_t bufferp, 1707 __in size_t buffer_size 1708 ) 1709 { 1710 const efx_lic_ops_t *elop = enp->en_elop; 1711 efx_rc_t rc; 1712 1713 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1714 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1715 1716 if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0) 1717 goto fail1; 1718 1719 return (0); 1720 1721 fail1: 1722 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1723 1724 return (rc); 1725 } 1726 1727 1728 __checkReturn efx_rc_t 1729 efx_lic_finish_partition( 1730 __in efx_nic_t *enp, 1731 __in_bcount(buffer_size) 1732 caddr_t bufferp, 1733 __in size_t buffer_size 1734 ) 1735 { 1736 const efx_lic_ops_t *elop = enp->en_elop; 1737 efx_rc_t rc; 1738 1739 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1740 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); 1741 1742 if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0) 1743 goto fail1; 1744 1745 return (0); 1746 1747 fail1: 1748 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1749 1750 return (rc); 1751 } 1752 1753 #endif /* EFSYS_OPT_LICENSING */ 1754