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