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