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