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