mfd: wm8350-i2c: Make sure the i2c regmap functions are compiled
[linux/fpc-iii.git] / drivers / char / tpm / tpm_ppi.c
blob811ad1e4d8024217371fbe8c8ec5e5eb77879ab5
1 #include <linux/acpi.h>
2 #include <acpi/acpi_drivers.h>
3 #include "tpm.h"
5 static const u8 tpm_ppi_uuid[] = {
6 0xA6, 0xFA, 0xDD, 0x3D,
7 0x1B, 0x36,
8 0xB4, 0x4E,
9 0xA4, 0x24,
10 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
12 static char *tpm_device_name = "TPM";
14 #define TPM_PPI_REVISION_ID 1
15 #define TPM_PPI_FN_VERSION 1
16 #define TPM_PPI_FN_SUBREQ 2
17 #define TPM_PPI_FN_GETREQ 3
18 #define TPM_PPI_FN_GETACT 4
19 #define TPM_PPI_FN_GETRSP 5
20 #define TPM_PPI_FN_SUBREQ2 7
21 #define TPM_PPI_FN_GETOPR 8
22 #define PPI_TPM_REQ_MAX 22
23 #define PPI_VS_REQ_START 128
24 #define PPI_VS_REQ_END 255
25 #define PPI_VERSION_LEN 3
27 static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
28 void **return_value)
30 acpi_status status = AE_OK;
31 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
33 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) {
34 if (strstr(buffer.pointer, context) != NULL) {
35 *return_value = handle;
36 status = AE_CTRL_TERMINATE;
38 kfree(buffer.pointer);
41 return status;
44 static inline void ppi_assign_params(union acpi_object params[4],
45 u64 function_num)
47 params[0].type = ACPI_TYPE_BUFFER;
48 params[0].buffer.length = sizeof(tpm_ppi_uuid);
49 params[0].buffer.pointer = (char *)tpm_ppi_uuid;
50 params[1].type = ACPI_TYPE_INTEGER;
51 params[1].integer.value = TPM_PPI_REVISION_ID;
52 params[2].type = ACPI_TYPE_INTEGER;
53 params[2].integer.value = function_num;
54 params[3].type = ACPI_TYPE_PACKAGE;
55 params[3].package.count = 0;
56 params[3].package.elements = NULL;
59 static ssize_t tpm_show_ppi_version(struct device *dev,
60 struct device_attribute *attr, char *buf)
62 acpi_handle handle;
63 acpi_status status;
64 struct acpi_object_list input;
65 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
66 union acpi_object params[4];
67 union acpi_object *obj;
69 input.count = 4;
70 ppi_assign_params(params, TPM_PPI_FN_VERSION);
71 input.pointer = params;
72 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
73 ACPI_UINT32_MAX, ppi_callback, NULL,
74 tpm_device_name, &handle);
75 if (ACPI_FAILURE(status))
76 return -ENXIO;
78 status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
79 ACPI_TYPE_STRING);
80 if (ACPI_FAILURE(status))
81 return -ENOMEM;
82 obj = (union acpi_object *)output.pointer;
83 status = scnprintf(buf, PAGE_SIZE, "%s\n", obj->string.pointer);
84 kfree(output.pointer);
85 return status;
88 static ssize_t tpm_show_ppi_request(struct device *dev,
89 struct device_attribute *attr, char *buf)
91 acpi_handle handle;
92 acpi_status status;
93 struct acpi_object_list input;
94 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
95 union acpi_object params[4];
96 union acpi_object *ret_obj;
98 input.count = 4;
99 ppi_assign_params(params, TPM_PPI_FN_GETREQ);
100 input.pointer = params;
101 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
102 ACPI_UINT32_MAX, ppi_callback, NULL,
103 tpm_device_name, &handle);
104 if (ACPI_FAILURE(status))
105 return -ENXIO;
107 status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
108 ACPI_TYPE_PACKAGE);
109 if (ACPI_FAILURE(status))
110 return -ENOMEM;
112 * output.pointer should be of package type, including two integers.
113 * The first is function return code, 0 means success and 1 means
114 * error. The second is pending TPM operation requested by the OS, 0
115 * means none and >0 means operation value.
117 ret_obj = ((union acpi_object *)output.pointer)->package.elements;
118 if (ret_obj->type == ACPI_TYPE_INTEGER) {
119 if (ret_obj->integer.value) {
120 status = -EFAULT;
121 goto cleanup;
123 ret_obj++;
124 if (ret_obj->type == ACPI_TYPE_INTEGER)
125 status = scnprintf(buf, PAGE_SIZE, "%llu\n",
126 ret_obj->integer.value);
127 else
128 status = -EINVAL;
129 } else {
130 status = -EINVAL;
132 cleanup:
133 kfree(output.pointer);
134 return status;
137 static ssize_t tpm_store_ppi_request(struct device *dev,
138 struct device_attribute *attr,
139 const char *buf, size_t count)
141 char version[PPI_VERSION_LEN + 1];
142 acpi_handle handle;
143 acpi_status status;
144 struct acpi_object_list input;
145 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
146 union acpi_object params[4];
147 union acpi_object obj;
148 u32 req;
149 u64 ret;
151 input.count = 4;
152 ppi_assign_params(params, TPM_PPI_FN_VERSION);
153 input.pointer = params;
154 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
155 ACPI_UINT32_MAX, ppi_callback, NULL,
156 tpm_device_name, &handle);
157 if (ACPI_FAILURE(status))
158 return -ENXIO;
160 status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
161 ACPI_TYPE_STRING);
162 if (ACPI_FAILURE(status))
163 return -ENOMEM;
164 strlcpy(version,
165 ((union acpi_object *)output.pointer)->string.pointer,
166 PPI_VERSION_LEN + 1);
167 kfree(output.pointer);
168 output.length = ACPI_ALLOCATE_BUFFER;
169 output.pointer = NULL;
171 * the function to submit TPM operation request to pre-os environment
172 * is updated with function index from SUBREQ to SUBREQ2 since PPI
173 * version 1.1
175 if (strcmp(version, "1.1") < 0)
176 params[2].integer.value = TPM_PPI_FN_SUBREQ;
177 else
178 params[2].integer.value = TPM_PPI_FN_SUBREQ2;
180 * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS
181 * accept buffer/string/integer type, but some BIOS accept buffer/
182 * string/package type. For PPI version 1.0 and 1.1, use buffer type
183 * for compatibility, and use package type since 1.2 according to spec.
185 if (strcmp(version, "1.2") < 0) {
186 params[3].type = ACPI_TYPE_BUFFER;
187 params[3].buffer.length = sizeof(req);
188 sscanf(buf, "%d", &req);
189 params[3].buffer.pointer = (char *)&req;
190 } else {
191 params[3].package.count = 1;
192 obj.type = ACPI_TYPE_INTEGER;
193 sscanf(buf, "%llu", &obj.integer.value);
194 params[3].package.elements = &obj;
197 status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
198 ACPI_TYPE_INTEGER);
199 if (ACPI_FAILURE(status))
200 return -ENOMEM;
201 ret = ((union acpi_object *)output.pointer)->integer.value;
202 if (ret == 0)
203 status = (acpi_status)count;
204 else if (ret == 1)
205 status = -EPERM;
206 else
207 status = -EFAULT;
208 kfree(output.pointer);
209 return status;
212 static ssize_t tpm_show_ppi_transition_action(struct device *dev,
213 struct device_attribute *attr,
214 char *buf)
216 char version[PPI_VERSION_LEN + 1];
217 acpi_handle handle;
218 acpi_status status;
219 struct acpi_object_list input;
220 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
221 union acpi_object params[4];
222 u32 ret;
223 char *info[] = {
224 "None",
225 "Shutdown",
226 "Reboot",
227 "OS Vendor-specific",
228 "Error",
230 input.count = 4;
231 ppi_assign_params(params, TPM_PPI_FN_VERSION);
232 input.pointer = params;
233 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
234 ACPI_UINT32_MAX, ppi_callback, NULL,
235 tpm_device_name, &handle);
236 if (ACPI_FAILURE(status))
237 return -ENXIO;
239 status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
240 ACPI_TYPE_STRING);
241 if (ACPI_FAILURE(status))
242 return -ENOMEM;
243 strlcpy(version,
244 ((union acpi_object *)output.pointer)->string.pointer,
245 PPI_VERSION_LEN + 1);
247 * PPI spec defines params[3].type as empty package, but some platforms
248 * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
249 * compatibility, define params[3].type as buffer, if PPI version < 1.2
251 if (strcmp(version, "1.2") < 0) {
252 params[3].type = ACPI_TYPE_BUFFER;
253 params[3].buffer.length = 0;
254 params[3].buffer.pointer = NULL;
256 params[2].integer.value = TPM_PPI_FN_GETACT;
257 kfree(output.pointer);
258 output.length = ACPI_ALLOCATE_BUFFER;
259 output.pointer = NULL;
260 status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
261 ACPI_TYPE_INTEGER);
262 if (ACPI_FAILURE(status))
263 return -ENOMEM;
264 ret = ((union acpi_object *)output.pointer)->integer.value;
265 if (ret < ARRAY_SIZE(info) - 1)
266 status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]);
267 else
268 status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret,
269 info[ARRAY_SIZE(info)-1]);
270 kfree(output.pointer);
271 return status;
274 static ssize_t tpm_show_ppi_response(struct device *dev,
275 struct device_attribute *attr,
276 char *buf)
278 acpi_handle handle;
279 acpi_status status;
280 struct acpi_object_list input;
281 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
282 union acpi_object params[4];
283 union acpi_object *ret_obj;
284 u64 req;
286 input.count = 4;
287 ppi_assign_params(params, TPM_PPI_FN_GETRSP);
288 input.pointer = params;
289 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
290 ACPI_UINT32_MAX, ppi_callback, NULL,
291 tpm_device_name, &handle);
292 if (ACPI_FAILURE(status))
293 return -ENXIO;
295 status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
296 ACPI_TYPE_PACKAGE);
297 if (ACPI_FAILURE(status))
298 return -ENOMEM;
300 * parameter output.pointer should be of package type, including
301 * 3 integers. The first means function return code, the second means
302 * most recent TPM operation request, and the last means response to
303 * the most recent TPM operation request. Only if the first is 0, and
304 * the second integer is not 0, the response makes sense.
306 ret_obj = ((union acpi_object *)output.pointer)->package.elements;
307 if (ret_obj->type != ACPI_TYPE_INTEGER) {
308 status = -EINVAL;
309 goto cleanup;
311 if (ret_obj->integer.value) {
312 status = -EFAULT;
313 goto cleanup;
315 ret_obj++;
316 if (ret_obj->type != ACPI_TYPE_INTEGER) {
317 status = -EINVAL;
318 goto cleanup;
320 if (ret_obj->integer.value) {
321 req = ret_obj->integer.value;
322 ret_obj++;
323 if (ret_obj->type != ACPI_TYPE_INTEGER) {
324 status = -EINVAL;
325 goto cleanup;
327 if (ret_obj->integer.value == 0)
328 status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
329 "0: Success");
330 else if (ret_obj->integer.value == 0xFFFFFFF0)
331 status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
332 "0xFFFFFFF0: User Abort");
333 else if (ret_obj->integer.value == 0xFFFFFFF1)
334 status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
335 "0xFFFFFFF1: BIOS Failure");
336 else if (ret_obj->integer.value >= 1 &&
337 ret_obj->integer.value <= 0x00000FFF)
338 status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
339 req, ret_obj->integer.value,
340 "Corresponding TPM error");
341 else
342 status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
343 req, ret_obj->integer.value,
344 "Error");
345 } else {
346 status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n",
347 ret_obj->integer.value, "No Recent Request");
349 cleanup:
350 kfree(output.pointer);
351 return status;
354 static ssize_t show_ppi_operations(char *buf, u32 start, u32 end)
356 char *str = buf;
357 char version[PPI_VERSION_LEN + 1];
358 acpi_handle handle;
359 acpi_status status;
360 struct acpi_object_list input;
361 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
362 union acpi_object params[4];
363 union acpi_object obj;
364 int i;
365 u32 ret;
366 char *info[] = {
367 "Not implemented",
368 "BIOS only",
369 "Blocked for OS by BIOS",
370 "User required",
371 "User not required",
373 input.count = 4;
374 ppi_assign_params(params, TPM_PPI_FN_VERSION);
375 input.pointer = params;
376 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
377 ACPI_UINT32_MAX, ppi_callback, NULL,
378 tpm_device_name, &handle);
379 if (ACPI_FAILURE(status))
380 return -ENXIO;
382 status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
383 ACPI_TYPE_STRING);
384 if (ACPI_FAILURE(status))
385 return -ENOMEM;
387 strlcpy(version,
388 ((union acpi_object *)output.pointer)->string.pointer,
389 PPI_VERSION_LEN + 1);
390 kfree(output.pointer);
391 output.length = ACPI_ALLOCATE_BUFFER;
392 output.pointer = NULL;
393 if (strcmp(version, "1.2") < 0)
394 return -EPERM;
396 params[2].integer.value = TPM_PPI_FN_GETOPR;
397 params[3].package.count = 1;
398 obj.type = ACPI_TYPE_INTEGER;
399 params[3].package.elements = &obj;
400 for (i = start; i <= end; i++) {
401 obj.integer.value = i;
402 status = acpi_evaluate_object_typed(handle, "_DSM",
403 &input, &output, ACPI_TYPE_INTEGER);
404 if (ACPI_FAILURE(status))
405 return -ENOMEM;
407 ret = ((union acpi_object *)output.pointer)->integer.value;
408 if (ret > 0 && ret < ARRAY_SIZE(info))
409 str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n",
410 i, ret, info[ret]);
411 kfree(output.pointer);
412 output.length = ACPI_ALLOCATE_BUFFER;
413 output.pointer = NULL;
415 return str - buf;
418 static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
419 struct device_attribute *attr,
420 char *buf)
422 return show_ppi_operations(buf, 0, PPI_TPM_REQ_MAX);
425 static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
426 struct device_attribute *attr,
427 char *buf)
429 return show_ppi_operations(buf, PPI_VS_REQ_START, PPI_VS_REQ_END);
432 static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
433 static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP,
434 tpm_show_ppi_request, tpm_store_ppi_request);
435 static DEVICE_ATTR(transition_action, S_IRUGO,
436 tpm_show_ppi_transition_action, NULL);
437 static DEVICE_ATTR(response, S_IRUGO, tpm_show_ppi_response, NULL);
438 static DEVICE_ATTR(tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations, NULL);
439 static DEVICE_ATTR(vs_operations, S_IRUGO, tpm_show_ppi_vs_operations, NULL);
441 static struct attribute *ppi_attrs[] = {
442 &dev_attr_version.attr,
443 &dev_attr_request.attr,
444 &dev_attr_transition_action.attr,
445 &dev_attr_response.attr,
446 &dev_attr_tcg_operations.attr,
447 &dev_attr_vs_operations.attr, NULL,
449 static struct attribute_group ppi_attr_grp = {
450 .name = "ppi",
451 .attrs = ppi_attrs
454 int tpm_add_ppi(struct kobject *parent)
456 return sysfs_create_group(parent, &ppi_attr_grp);
458 EXPORT_SYMBOL_GPL(tpm_add_ppi);
460 void tpm_remove_ppi(struct kobject *parent)
462 sysfs_remove_group(parent, &ppi_attr_grp);
464 EXPORT_SYMBOL_GPL(tpm_remove_ppi);
466 MODULE_LICENSE("GPL");