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