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