Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2012-2014 Intel Corporation
0004  *
0005  * Authors:
0006  * Xiaoyan Zhang <xiaoyan.zhang@intel.com>
0007  * Jiang Liu <jiang.liu@linux.intel.com>
0008  * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
0009  *
0010  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
0011  *
0012  * This file contains implementation of the sysfs interface for PPI.
0013  */
0014 
0015 
0016 #include <linux/acpi.h>
0017 #include "tpm.h"
0018 
0019 #define TPM_PPI_REVISION_ID_1   1
0020 #define TPM_PPI_REVISION_ID_2   2
0021 #define TPM_PPI_FN_VERSION  1
0022 #define TPM_PPI_FN_SUBREQ   2
0023 #define TPM_PPI_FN_GETREQ   3
0024 #define TPM_PPI_FN_GETACT   4
0025 #define TPM_PPI_FN_GETRSP   5
0026 #define TPM_PPI_FN_SUBREQ2  7
0027 #define TPM_PPI_FN_GETOPR   8
0028 #define PPI_TPM_REQ_MAX     101 /* PPI 1.3 for TPM 2 */
0029 #define PPI_VS_REQ_START    128
0030 #define PPI_VS_REQ_END      255
0031 
0032 static const guid_t tpm_ppi_guid =
0033     GUID_INIT(0x3DDDFAA6, 0x361B, 0x4EB4,
0034           0xA4, 0x24, 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53);
0035 
0036 static bool tpm_ppi_req_has_parameter(u64 req)
0037 {
0038     return req == 23;
0039 }
0040 
0041 static inline union acpi_object *
0042 tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type,
0043          union acpi_object *argv4, u64 rev)
0044 {
0045     BUG_ON(!ppi_handle);
0046     return acpi_evaluate_dsm_typed(ppi_handle, &tpm_ppi_guid,
0047                        rev, func, argv4, type);
0048 }
0049 
0050 static ssize_t tpm_show_ppi_version(struct device *dev,
0051                     struct device_attribute *attr, char *buf)
0052 {
0053     struct tpm_chip *chip = to_tpm_chip(dev);
0054 
0055     return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version);
0056 }
0057 
0058 static ssize_t tpm_show_ppi_request(struct device *dev,
0059                     struct device_attribute *attr, char *buf)
0060 {
0061     ssize_t size = -EINVAL;
0062     union acpi_object *obj;
0063     struct tpm_chip *chip = to_tpm_chip(dev);
0064     u64 rev = TPM_PPI_REVISION_ID_2;
0065     u64 req;
0066 
0067     if (strcmp(chip->ppi_version, "1.2") < 0)
0068         rev = TPM_PPI_REVISION_ID_1;
0069 
0070     obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ,
0071                ACPI_TYPE_PACKAGE, NULL, rev);
0072     if (!obj)
0073         return -ENXIO;
0074 
0075     /*
0076      * output.pointer should be of package type, including two integers.
0077      * The first is function return code, 0 means success and 1 means
0078      * error. The second is pending TPM operation requested by the OS, 0
0079      * means none and >0 means operation value.
0080      */
0081     if (obj->package.count == 3 &&
0082         obj->package.elements[0].type == ACPI_TYPE_INTEGER &&
0083         obj->package.elements[1].type == ACPI_TYPE_INTEGER &&
0084         obj->package.elements[2].type == ACPI_TYPE_INTEGER) {
0085         if (obj->package.elements[0].integer.value)
0086             size = -EFAULT;
0087         else {
0088             req = obj->package.elements[1].integer.value;
0089             if (tpm_ppi_req_has_parameter(req))
0090                 size = scnprintf(buf, PAGE_SIZE,
0091                     "%llu %llu\n", req,
0092                     obj->package.elements[2].integer.value);
0093             else
0094                 size = scnprintf(buf, PAGE_SIZE,
0095                         "%llu\n", req);
0096         }
0097     } else if (obj->package.count == 2 &&
0098         obj->package.elements[0].type == ACPI_TYPE_INTEGER &&
0099         obj->package.elements[1].type == ACPI_TYPE_INTEGER) {
0100         if (obj->package.elements[0].integer.value)
0101             size = -EFAULT;
0102         else
0103             size = scnprintf(buf, PAGE_SIZE, "%llu\n",
0104                  obj->package.elements[1].integer.value);
0105     }
0106 
0107     ACPI_FREE(obj);
0108 
0109     return size;
0110 }
0111 
0112 static ssize_t tpm_store_ppi_request(struct device *dev,
0113                      struct device_attribute *attr,
0114                      const char *buf, size_t count)
0115 {
0116     u32 req;
0117     u64 ret;
0118     int func = TPM_PPI_FN_SUBREQ;
0119     union acpi_object *obj, tmp[2];
0120     union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(2, tmp);
0121     struct tpm_chip *chip = to_tpm_chip(dev);
0122     u64 rev = TPM_PPI_REVISION_ID_1;
0123 
0124     /*
0125      * the function to submit TPM operation request to pre-os environment
0126      * is updated with function index from SUBREQ to SUBREQ2 since PPI
0127      * version 1.1
0128      */
0129     if (acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid,
0130                TPM_PPI_REVISION_ID_1, 1 << TPM_PPI_FN_SUBREQ2))
0131         func = TPM_PPI_FN_SUBREQ2;
0132 
0133     /*
0134      * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS
0135      * accept buffer/string/integer type, but some BIOS accept buffer/
0136      * string/package type. For PPI version 1.0 and 1.1, use buffer type
0137      * for compatibility, and use package type since 1.2 according to spec.
0138      */
0139     if (strcmp(chip->ppi_version, "1.3") == 0) {
0140         if (sscanf(buf, "%llu %llu", &tmp[0].integer.value,
0141                &tmp[1].integer.value) != 2)
0142             goto ppi12;
0143         rev = TPM_PPI_REVISION_ID_2;
0144         tmp[0].type = ACPI_TYPE_INTEGER;
0145         tmp[1].type = ACPI_TYPE_INTEGER;
0146     } else if (strcmp(chip->ppi_version, "1.2") < 0) {
0147         if (sscanf(buf, "%d", &req) != 1)
0148             return -EINVAL;
0149         argv4.type = ACPI_TYPE_BUFFER;
0150         argv4.buffer.length = sizeof(req);
0151         argv4.buffer.pointer = (u8 *)&req;
0152     } else {
0153 ppi12:
0154         argv4.package.count = 1;
0155         tmp[0].type = ACPI_TYPE_INTEGER;
0156         if (sscanf(buf, "%llu", &tmp[0].integer.value) != 1)
0157             return -EINVAL;
0158     }
0159 
0160     obj = tpm_eval_dsm(chip->acpi_dev_handle, func, ACPI_TYPE_INTEGER,
0161                &argv4, rev);
0162     if (!obj) {
0163         return -ENXIO;
0164     } else {
0165         ret = obj->integer.value;
0166         ACPI_FREE(obj);
0167     }
0168 
0169     if (ret == 0)
0170         return (acpi_status)count;
0171 
0172     return (ret == 1) ? -EPERM : -EFAULT;
0173 }
0174 
0175 static ssize_t tpm_show_ppi_transition_action(struct device *dev,
0176                           struct device_attribute *attr,
0177                           char *buf)
0178 {
0179     u32 ret;
0180     acpi_status status;
0181     union acpi_object *obj = NULL;
0182     union acpi_object tmp = {
0183         .buffer.type = ACPI_TYPE_BUFFER,
0184         .buffer.length = 0,
0185         .buffer.pointer = NULL
0186     };
0187     struct tpm_chip *chip = to_tpm_chip(dev);
0188 
0189     static char *info[] = {
0190         "None",
0191         "Shutdown",
0192         "Reboot",
0193         "OS Vendor-specific",
0194         "Error",
0195     };
0196 
0197     /*
0198      * PPI spec defines params[3].type as empty package, but some platforms
0199      * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
0200      * compatibility, define params[3].type as buffer, if PPI version < 1.2
0201      */
0202     if (strcmp(chip->ppi_version, "1.2") < 0)
0203         obj = &tmp;
0204     obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETACT,
0205                ACPI_TYPE_INTEGER, obj, TPM_PPI_REVISION_ID_1);
0206     if (!obj) {
0207         return -ENXIO;
0208     } else {
0209         ret = obj->integer.value;
0210         ACPI_FREE(obj);
0211     }
0212 
0213     if (ret < ARRAY_SIZE(info) - 1)
0214         status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]);
0215     else
0216         status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret,
0217                    info[ARRAY_SIZE(info)-1]);
0218     return status;
0219 }
0220 
0221 static ssize_t tpm_show_ppi_response(struct device *dev,
0222                      struct device_attribute *attr,
0223                      char *buf)
0224 {
0225     acpi_status status = -EINVAL;
0226     union acpi_object *obj, *ret_obj;
0227     u64 req, res;
0228     struct tpm_chip *chip = to_tpm_chip(dev);
0229 
0230     obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP,
0231                ACPI_TYPE_PACKAGE, NULL, TPM_PPI_REVISION_ID_1);
0232     if (!obj)
0233         return -ENXIO;
0234 
0235     /*
0236      * parameter output.pointer should be of package type, including
0237      * 3 integers. The first means function return code, the second means
0238      * most recent TPM operation request, and the last means response to
0239      * the most recent TPM operation request. Only if the first is 0, and
0240      * the second integer is not 0, the response makes sense.
0241      */
0242     ret_obj = obj->package.elements;
0243     if (obj->package.count < 3 ||
0244         ret_obj[0].type != ACPI_TYPE_INTEGER ||
0245         ret_obj[1].type != ACPI_TYPE_INTEGER ||
0246         ret_obj[2].type != ACPI_TYPE_INTEGER)
0247         goto cleanup;
0248 
0249     if (ret_obj[0].integer.value) {
0250         status = -EFAULT;
0251         goto cleanup;
0252     }
0253 
0254     req = ret_obj[1].integer.value;
0255     res = ret_obj[2].integer.value;
0256     if (req) {
0257         if (res == 0)
0258             status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
0259                        "0: Success");
0260         else if (res == 0xFFFFFFF0)
0261             status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
0262                        "0xFFFFFFF0: User Abort");
0263         else if (res == 0xFFFFFFF1)
0264             status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
0265                        "0xFFFFFFF1: BIOS Failure");
0266         else if (res >= 1 && res <= 0x00000FFF)
0267             status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
0268                        req, res, "Corresponding TPM error");
0269         else
0270             status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
0271                        req, res, "Error");
0272     } else {
0273         status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n",
0274                    req, "No Recent Request");
0275     }
0276 
0277 cleanup:
0278     ACPI_FREE(obj);
0279     return status;
0280 }
0281 
0282 static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start,
0283                    u32 end)
0284 {
0285     int i;
0286     u32 ret;
0287     char *str = buf;
0288     union acpi_object *obj, tmp;
0289     union acpi_object argv = ACPI_INIT_DSM_ARGV4(1, &tmp);
0290 
0291     static char *info[] = {
0292         "Not implemented",
0293         "BIOS only",
0294         "Blocked for OS by BIOS",
0295         "User required",
0296         "User not required",
0297     };
0298 
0299     if (!acpi_check_dsm(dev_handle, &tpm_ppi_guid, TPM_PPI_REVISION_ID_1,
0300                 1 << TPM_PPI_FN_GETOPR))
0301         return -EPERM;
0302 
0303     tmp.integer.type = ACPI_TYPE_INTEGER;
0304     for (i = start; i <= end; i++) {
0305         tmp.integer.value = i;
0306         obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR,
0307                    ACPI_TYPE_INTEGER, &argv,
0308                    TPM_PPI_REVISION_ID_1);
0309         if (!obj) {
0310             return -ENOMEM;
0311         } else {
0312             ret = obj->integer.value;
0313             ACPI_FREE(obj);
0314         }
0315 
0316         if (ret > 0 && ret < ARRAY_SIZE(info))
0317             str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n",
0318                      i, ret, info[ret]);
0319     }
0320 
0321     return str - buf;
0322 }
0323 
0324 static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
0325                        struct device_attribute *attr,
0326                        char *buf)
0327 {
0328     struct tpm_chip *chip = to_tpm_chip(dev);
0329 
0330     return show_ppi_operations(chip->acpi_dev_handle, buf, 0,
0331                    PPI_TPM_REQ_MAX);
0332 }
0333 
0334 static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
0335                       struct device_attribute *attr,
0336                       char *buf)
0337 {
0338     struct tpm_chip *chip = to_tpm_chip(dev);
0339 
0340     return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START,
0341                    PPI_VS_REQ_END);
0342 }
0343 
0344 static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
0345 static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP,
0346            tpm_show_ppi_request, tpm_store_ppi_request);
0347 static DEVICE_ATTR(transition_action, S_IRUGO,
0348            tpm_show_ppi_transition_action, NULL);
0349 static DEVICE_ATTR(response, S_IRUGO, tpm_show_ppi_response, NULL);
0350 static DEVICE_ATTR(tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations, NULL);
0351 static DEVICE_ATTR(vs_operations, S_IRUGO, tpm_show_ppi_vs_operations, NULL);
0352 
0353 static struct attribute *ppi_attrs[] = {
0354     &dev_attr_version.attr,
0355     &dev_attr_request.attr,
0356     &dev_attr_transition_action.attr,
0357     &dev_attr_response.attr,
0358     &dev_attr_tcg_operations.attr,
0359     &dev_attr_vs_operations.attr, NULL,
0360 };
0361 static const struct attribute_group ppi_attr_grp = {
0362     .name = "ppi",
0363     .attrs = ppi_attrs
0364 };
0365 
0366 void tpm_add_ppi(struct tpm_chip *chip)
0367 {
0368     union acpi_object *obj;
0369 
0370     if (!chip->acpi_dev_handle)
0371         return;
0372 
0373     if (!acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid,
0374                 TPM_PPI_REVISION_ID_1, 1 << TPM_PPI_FN_VERSION))
0375         return;
0376 
0377     /* Cache PPI version string. */
0378     obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, &tpm_ppi_guid,
0379                       TPM_PPI_REVISION_ID_1,
0380                       TPM_PPI_FN_VERSION,
0381                       NULL, ACPI_TYPE_STRING);
0382     if (obj) {
0383         strlcpy(chip->ppi_version, obj->string.pointer,
0384             sizeof(chip->ppi_version));
0385         ACPI_FREE(obj);
0386     }
0387 
0388     chip->groups[chip->groups_cnt++] = &ppi_attr_grp;
0389 }