Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2012-2014 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Xiaoyan Zhang <xiaoyan.zhang@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Jiang Liu <jiang.liu@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * This file contains implementation of the sysfs interface for PPI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "tpm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define TPM_PPI_REVISION_ID_1	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define TPM_PPI_REVISION_ID_2	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define TPM_PPI_FN_VERSION	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define TPM_PPI_FN_SUBREQ	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define TPM_PPI_FN_GETREQ	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define TPM_PPI_FN_GETACT	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define TPM_PPI_FN_GETRSP	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define TPM_PPI_FN_SUBREQ2	7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define TPM_PPI_FN_GETOPR	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define PPI_TPM_REQ_MAX		101 /* PPI 1.3 for TPM 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define PPI_VS_REQ_START	128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define PPI_VS_REQ_END		255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static const guid_t tpm_ppi_guid =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	GUID_INIT(0x3DDDFAA6, 0x361B, 0x4EB4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		  0xA4, 0x24, 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static bool tpm_ppi_req_has_parameter(u64 req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	return req == 23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static inline union acpi_object *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	     union acpi_object *argv4, u64 rev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	BUG_ON(!ppi_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	return acpi_evaluate_dsm_typed(ppi_handle, &tpm_ppi_guid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 				       rev, func, argv4, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) static ssize_t tpm_show_ppi_version(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 				    struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	struct tpm_chip *chip = to_tpm_chip(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) static ssize_t tpm_show_ppi_request(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 				    struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	ssize_t size = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	union acpi_object *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	struct tpm_chip *chip = to_tpm_chip(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	u64 rev = TPM_PPI_REVISION_ID_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	u64 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (strcmp(chip->ppi_version, "1.2") < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		rev = TPM_PPI_REVISION_ID_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			   ACPI_TYPE_PACKAGE, NULL, rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (!obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	 * output.pointer should be of package type, including two integers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	 * The first is function return code, 0 means success and 1 means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	 * error. The second is pending TPM operation requested by the OS, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	 * means none and >0 means operation value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (obj->package.count == 3 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	    obj->package.elements[0].type == ACPI_TYPE_INTEGER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	    obj->package.elements[1].type == ACPI_TYPE_INTEGER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	    obj->package.elements[2].type == ACPI_TYPE_INTEGER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		if (obj->package.elements[0].integer.value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			size = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			req = obj->package.elements[1].integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			if (tpm_ppi_req_has_parameter(req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 				size = scnprintf(buf, PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 				    "%llu %llu\n", req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 				    obj->package.elements[2].integer.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 				size = scnprintf(buf, PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 						"%llu\n", req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	} else if (obj->package.count == 2 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	    obj->package.elements[0].type == ACPI_TYPE_INTEGER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	    obj->package.elements[1].type == ACPI_TYPE_INTEGER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		if (obj->package.elements[0].integer.value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			size = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			size = scnprintf(buf, PAGE_SIZE, "%llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 				 obj->package.elements[1].integer.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	ACPI_FREE(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static ssize_t tpm_store_ppi_request(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 				     struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 				     const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	u32 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	u64 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	int func = TPM_PPI_FN_SUBREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	union acpi_object *obj, tmp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(2, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	struct tpm_chip *chip = to_tpm_chip(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	u64 rev = TPM_PPI_REVISION_ID_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	 * the function to submit TPM operation request to pre-os environment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	 * is updated with function index from SUBREQ to SUBREQ2 since PPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	 * version 1.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	if (acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 			   TPM_PPI_REVISION_ID_1, 1 << TPM_PPI_FN_SUBREQ2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		func = TPM_PPI_FN_SUBREQ2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	 * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	 * accept buffer/string/integer type, but some BIOS accept buffer/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	 * string/package type. For PPI version 1.0 and 1.1, use buffer type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	 * for compatibility, and use package type since 1.2 according to spec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (strcmp(chip->ppi_version, "1.3") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		if (sscanf(buf, "%llu %llu", &tmp[0].integer.value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			   &tmp[1].integer.value) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			goto ppi12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		rev = TPM_PPI_REVISION_ID_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		tmp[0].type = ACPI_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		tmp[1].type = ACPI_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	} else if (strcmp(chip->ppi_version, "1.2") < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		if (sscanf(buf, "%d", &req) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		argv4.type = ACPI_TYPE_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		argv4.buffer.length = sizeof(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		argv4.buffer.pointer = (u8 *)&req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ppi12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		argv4.package.count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		tmp[0].type = ACPI_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		if (sscanf(buf, "%llu", &tmp[0].integer.value) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	obj = tpm_eval_dsm(chip->acpi_dev_handle, func, ACPI_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			   &argv4, rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (!obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		ret = obj->integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		ACPI_FREE(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		return (acpi_status)count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	return (ret == 1) ? -EPERM : -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static ssize_t tpm_show_ppi_transition_action(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 					      struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 					      char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	union acpi_object *obj = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	union acpi_object tmp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		.buffer.type = ACPI_TYPE_BUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		.buffer.length = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		.buffer.pointer = NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	struct tpm_chip *chip = to_tpm_chip(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	static char *info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		"None",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		"Shutdown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		"Reboot",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		"OS Vendor-specific",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		"Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	 * PPI spec defines params[3].type as empty package, but some platforms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	 * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	 * compatibility, define params[3].type as buffer, if PPI version < 1.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	if (strcmp(chip->ppi_version, "1.2") < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		obj = &tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETACT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			   ACPI_TYPE_INTEGER, obj, TPM_PPI_REVISION_ID_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	if (!obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		ret = obj->integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		ACPI_FREE(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	if (ret < ARRAY_SIZE(info) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 				   info[ARRAY_SIZE(info)-1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static ssize_t tpm_show_ppi_response(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 				     struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 				     char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	acpi_status status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	union acpi_object *obj, *ret_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	u64 req, res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	struct tpm_chip *chip = to_tpm_chip(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			   ACPI_TYPE_PACKAGE, NULL, TPM_PPI_REVISION_ID_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	if (!obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	 * parameter output.pointer should be of package type, including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	 * 3 integers. The first means function return code, the second means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	 * most recent TPM operation request, and the last means response to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	 * the most recent TPM operation request. Only if the first is 0, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	 * the second integer is not 0, the response makes sense.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	ret_obj = obj->package.elements;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	if (obj->package.count < 3 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	    ret_obj[0].type != ACPI_TYPE_INTEGER ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	    ret_obj[1].type != ACPI_TYPE_INTEGER ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	    ret_obj[2].type != ACPI_TYPE_INTEGER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	if (ret_obj[0].integer.value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		status = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	req = ret_obj[1].integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	res = ret_obj[2].integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	if (req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		if (res == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 					   "0: Success");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		else if (res == 0xFFFFFFF0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 					   "0xFFFFFFF0: User Abort");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		else if (res == 0xFFFFFFF1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 					   "0xFFFFFFF1: BIOS Failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		else if (res >= 1 && res <= 0x00000FFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 					   req, res, "Corresponding TPM error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 			status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 					   req, res, "Error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 				   req, "No Recent Request");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	ACPI_FREE(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 				   u32 end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	char *str = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	union acpi_object *obj, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	union acpi_object argv = ACPI_INIT_DSM_ARGV4(1, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	static char *info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		"Not implemented",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		"BIOS only",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		"Blocked for OS by BIOS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		"User required",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		"User not required",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	if (!acpi_check_dsm(dev_handle, &tpm_ppi_guid, TPM_PPI_REVISION_ID_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 			    1 << TPM_PPI_FN_GETOPR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	tmp.integer.type = ACPI_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	for (i = start; i <= end; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		tmp.integer.value = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 				   ACPI_TYPE_INTEGER, &argv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 				   TPM_PPI_REVISION_ID_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		if (!obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			ret = obj->integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 			ACPI_FREE(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		if (ret > 0 && ret < ARRAY_SIZE(info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 					 i, ret, info[ret]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	return str - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 					   struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 					   char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	struct tpm_chip *chip = to_tpm_chip(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	return show_ppi_operations(chip->acpi_dev_handle, buf, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 				   PPI_TPM_REQ_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 					  struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 					  char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	struct tpm_chip *chip = to_tpm_chip(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 				   PPI_VS_REQ_END);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		   tpm_show_ppi_request, tpm_store_ppi_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static DEVICE_ATTR(transition_action, S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		   tpm_show_ppi_transition_action, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static DEVICE_ATTR(response, S_IRUGO, tpm_show_ppi_response, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static DEVICE_ATTR(tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static DEVICE_ATTR(vs_operations, S_IRUGO, tpm_show_ppi_vs_operations, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static struct attribute *ppi_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	&dev_attr_version.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	&dev_attr_request.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	&dev_attr_transition_action.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	&dev_attr_response.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	&dev_attr_tcg_operations.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	&dev_attr_vs_operations.attr, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static struct attribute_group ppi_attr_grp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	.name = "ppi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	.attrs = ppi_attrs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) void tpm_add_ppi(struct tpm_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	union acpi_object *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	if (!chip->acpi_dev_handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	if (!acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			    TPM_PPI_REVISION_ID_1, 1 << TPM_PPI_FN_VERSION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	/* Cache PPI version string. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, &tpm_ppi_guid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 				      TPM_PPI_REVISION_ID_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 				      TPM_PPI_FN_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 				      NULL, ACPI_TYPE_STRING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	if (obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		strlcpy(chip->ppi_version, obj->string.pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 			sizeof(chip->ppi_version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		ACPI_FREE(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	chip->groups[chip->groups_cnt++] = &ppi_attr_grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }