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