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