hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/char/tpm/tpm-chip.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2004 IBM Corporation
34 * Copyright (C) 2014 Intel Corporation
....@@ -12,12 +13,6 @@
1213 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
1314 *
1415 * TPM chip management routines.
15
- *
16
- * This program is free software; you can redistribute it and/or
17
- * modify it under the terms of the GNU General Public License as
18
- * published by the Free Software Foundation, version 2 of the
19
- * License.
20
- *
2116 */
2217
2318 #include <linux/poll.h>
....@@ -36,6 +31,112 @@
3631 struct class *tpm_class;
3732 struct class *tpmrm_class;
3833 dev_t tpm_devt;
34
+
35
+static int tpm_request_locality(struct tpm_chip *chip)
36
+{
37
+ int rc;
38
+
39
+ if (!chip->ops->request_locality)
40
+ return 0;
41
+
42
+ rc = chip->ops->request_locality(chip, 0);
43
+ if (rc < 0)
44
+ return rc;
45
+
46
+ chip->locality = rc;
47
+ return 0;
48
+}
49
+
50
+static void tpm_relinquish_locality(struct tpm_chip *chip)
51
+{
52
+ int rc;
53
+
54
+ if (!chip->ops->relinquish_locality)
55
+ return;
56
+
57
+ rc = chip->ops->relinquish_locality(chip, chip->locality);
58
+ if (rc)
59
+ dev_err(&chip->dev, "%s: : error %d\n", __func__, rc);
60
+
61
+ chip->locality = -1;
62
+}
63
+
64
+static int tpm_cmd_ready(struct tpm_chip *chip)
65
+{
66
+ if (!chip->ops->cmd_ready)
67
+ return 0;
68
+
69
+ return chip->ops->cmd_ready(chip);
70
+}
71
+
72
+static int tpm_go_idle(struct tpm_chip *chip)
73
+{
74
+ if (!chip->ops->go_idle)
75
+ return 0;
76
+
77
+ return chip->ops->go_idle(chip);
78
+}
79
+
80
+static void tpm_clk_enable(struct tpm_chip *chip)
81
+{
82
+ if (chip->ops->clk_enable)
83
+ chip->ops->clk_enable(chip, true);
84
+}
85
+
86
+static void tpm_clk_disable(struct tpm_chip *chip)
87
+{
88
+ if (chip->ops->clk_enable)
89
+ chip->ops->clk_enable(chip, false);
90
+}
91
+
92
+/**
93
+ * tpm_chip_start() - power on the TPM
94
+ * @chip: a TPM chip to use
95
+ *
96
+ * Return:
97
+ * * The response length - OK
98
+ * * -errno - A system error
99
+ */
100
+int tpm_chip_start(struct tpm_chip *chip)
101
+{
102
+ int ret;
103
+
104
+ tpm_clk_enable(chip);
105
+
106
+ if (chip->locality == -1) {
107
+ ret = tpm_request_locality(chip);
108
+ if (ret) {
109
+ tpm_clk_disable(chip);
110
+ return ret;
111
+ }
112
+ }
113
+
114
+ ret = tpm_cmd_ready(chip);
115
+ if (ret) {
116
+ tpm_relinquish_locality(chip);
117
+ tpm_clk_disable(chip);
118
+ return ret;
119
+ }
120
+
121
+ return 0;
122
+}
123
+EXPORT_SYMBOL_GPL(tpm_chip_start);
124
+
125
+/**
126
+ * tpm_chip_stop() - power off the TPM
127
+ * @chip: a TPM chip to use
128
+ *
129
+ * Return:
130
+ * * The response length - OK
131
+ * * -errno - A system error
132
+ */
133
+void tpm_chip_stop(struct tpm_chip *chip)
134
+{
135
+ tpm_go_idle(chip);
136
+ tpm_relinquish_locality(chip);
137
+ tpm_clk_disable(chip);
138
+}
139
+EXPORT_SYMBOL_GPL(tpm_chip_stop);
39140
40141 /**
41142 * tpm_try_get_ops() - Get a ref to the tpm_chip
....@@ -56,10 +157,17 @@
56157
57158 down_read(&chip->ops_sem);
58159 if (!chip->ops)
160
+ goto out_ops;
161
+
162
+ mutex_lock(&chip->tpm_mutex);
163
+ rc = tpm_chip_start(chip);
164
+ if (rc)
59165 goto out_lock;
60166
61167 return 0;
62168 out_lock:
169
+ mutex_unlock(&chip->tpm_mutex);
170
+out_ops:
63171 up_read(&chip->ops_sem);
64172 put_device(&chip->dev);
65173 return rc;
....@@ -75,6 +183,8 @@
75183 */
76184 void tpm_put_ops(struct tpm_chip *chip)
77185 {
186
+ tpm_chip_stop(chip);
187
+ mutex_unlock(&chip->tpm_mutex);
78188 up_read(&chip->ops_sem);
79189 put_device(&chip->dev);
80190 }
....@@ -160,15 +270,8 @@
160270 kfree(chip->log.bios_event_log);
161271 kfree(chip->work_space.context_buf);
162272 kfree(chip->work_space.session_buf);
273
+ kfree(chip->allocated_banks);
163274 kfree(chip);
164
-}
165
-
166
-static void tpm_devs_release(struct device *dev)
167
-{
168
- struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
169
-
170
- /* release the master device reference */
171
- put_device(&chip->dev);
172275 }
173276
174277 /**
....@@ -176,12 +279,9 @@
176279 * @dev: device to which the chip is associated.
177280 *
178281 * Issues a TPM2_Shutdown command prior to loss of power, as required by the
179
- * TPM 2.0 spec.
180
- * Then, calls bus- and device- specific shutdown code.
282
+ * TPM 2.0 spec. Then, calls bus- and device- specific shutdown code.
181283 *
182
- * XXX: This codepath relies on the fact that sysfs is not enabled for
183
- * TPM2: sysfs uses an implicit lock on chip->ops, so this could race if TPM2
184
- * has sysfs support enabled before TPM sysfs's implicit locking is fixed.
284
+ * Return: always 0 (i.e. success)
185285 */
186286 static int tpm_class_shutdown(struct device *dev)
187287 {
....@@ -189,8 +289,10 @@
189289
190290 down_write(&chip->ops_sem);
191291 if (chip->flags & TPM_CHIP_FLAG_TPM2) {
192
- tpm2_shutdown(chip, TPM2_SU_CLEAR);
193
- chip->ops = NULL;
292
+ if (!tpm_chip_start(chip)) {
293
+ tpm2_shutdown(chip, TPM2_SU_CLEAR);
294
+ tpm_chip_stop(chip);
295
+ }
194296 }
195297 chip->ops = NULL;
196298 up_write(&chip->ops_sem);
....@@ -234,7 +336,6 @@
234336 chip->dev_num = rc;
235337
236338 device_initialize(&chip->dev);
237
- device_initialize(&chip->devs);
238339
239340 chip->dev.class = tpm_class;
240341 chip->dev.class->shutdown_pre = tpm_class_shutdown;
....@@ -242,29 +343,12 @@
242343 chip->dev.parent = pdev;
243344 chip->dev.groups = chip->groups;
244345
245
- chip->devs.parent = pdev;
246
- chip->devs.class = tpmrm_class;
247
- chip->devs.release = tpm_devs_release;
248
- /* get extra reference on main device to hold on
249
- * behalf of devs. This holds the chip structure
250
- * while cdevs is in use. The corresponding put
251
- * is in the tpm_devs_release (TPM2 only)
252
- */
253
- if (chip->flags & TPM_CHIP_FLAG_TPM2)
254
- get_device(&chip->dev);
255
-
256346 if (chip->dev_num == 0)
257347 chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
258348 else
259349 chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
260350
261
- chip->devs.devt =
262
- MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
263
-
264351 rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
265
- if (rc)
266
- goto out;
267
- rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
268352 if (rc)
269353 goto out;
270354
....@@ -272,9 +356,7 @@
272356 chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
273357
274358 cdev_init(&chip->cdev, &tpm_fops);
275
- cdev_init(&chip->cdevs, &tpmrm_fops);
276359 chip->cdev.owner = THIS_MODULE;
277
- chip->cdevs.owner = THIS_MODULE;
278360
279361 rc = tpm2_init_space(&chip->work_space, TPM2_SPACE_BUFFER_SIZE);
280362 if (rc) {
....@@ -286,7 +368,6 @@
286368 return chip;
287369
288370 out:
289
- put_device(&chip->devs);
290371 put_device(&chip->dev);
291372 return ERR_PTR(rc);
292373 }
....@@ -335,14 +416,9 @@
335416 }
336417
337418 if (chip->flags & TPM_CHIP_FLAG_TPM2) {
338
- rc = cdev_device_add(&chip->cdevs, &chip->devs);
339
- if (rc) {
340
- dev_err(&chip->devs,
341
- "unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
342
- dev_name(&chip->devs), MAJOR(chip->devs.devt),
343
- MINOR(chip->devs.devt), rc);
344
- return rc;
345
- }
419
+ rc = tpm_devs_add(chip);
420
+ if (rc)
421
+ goto err_del_cdev;
346422 }
347423
348424 /* Make the chip available. */
....@@ -350,6 +426,10 @@
350426 idr_replace(&dev_nums_idr, chip, chip->dev_num);
351427 mutex_unlock(&idr_lock);
352428
429
+ return 0;
430
+
431
+err_del_cdev:
432
+ cdev_device_del(&chip->cdev, &chip->dev);
353433 return rc;
354434 }
355435
....@@ -364,8 +444,12 @@
364444
365445 /* Make the driver uncallable. */
366446 down_write(&chip->ops_sem);
367
- if (chip->flags & TPM_CHIP_FLAG_TPM2)
368
- tpm2_shutdown(chip, TPM2_SU_CLEAR);
447
+ if (chip->flags & TPM_CHIP_FLAG_TPM2) {
448
+ if (!tpm_chip_start(chip)) {
449
+ tpm2_shutdown(chip, TPM2_SU_CLEAR);
450
+ tpm_chip_stop(chip);
451
+ }
452
+ }
369453 chip->ops = NULL;
370454 up_write(&chip->ops_sem);
371455 }
....@@ -395,15 +479,15 @@
395479 if (chip->flags & (TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_VIRTUAL))
396480 return 0;
397481
398
- rc = __compat_only_sysfs_link_entry_to_kobj(
399
- &chip->dev.parent->kobj, &chip->dev.kobj, "ppi");
482
+ rc = compat_only_sysfs_link_entry_to_kobj(
483
+ &chip->dev.parent->kobj, &chip->dev.kobj, "ppi", NULL);
400484 if (rc && rc != -ENOENT)
401485 return rc;
402486
403487 /* All the names from tpm-sysfs */
404488 for (i = chip->groups[0]->attrs; *i != NULL; ++i) {
405
- rc = __compat_only_sysfs_link_entry_to_kobj(
406
- &chip->dev.parent->kobj, &chip->dev.kobj, (*i)->name);
489
+ rc = compat_only_sysfs_link_entry_to_kobj(
490
+ &chip->dev.parent->kobj, &chip->dev.kobj, (*i)->name, NULL);
407491 if (rc) {
408492 tpm_del_legacy_sysfs(chip);
409493 return rc;
....@@ -432,6 +516,20 @@
432516 return hwrng_register(&chip->hwrng);
433517 }
434518
519
+static int tpm_get_pcr_allocation(struct tpm_chip *chip)
520
+{
521
+ int rc;
522
+
523
+ rc = (chip->flags & TPM_CHIP_FLAG_TPM2) ?
524
+ tpm2_get_pcr_allocation(chip) :
525
+ tpm1_get_pcr_allocation(chip);
526
+
527
+ if (rc > 0)
528
+ return -ENODEV;
529
+
530
+ return rc;
531
+}
532
+
435533 /*
436534 * tpm_chip_register() - create a character device for the TPM chip
437535 * @chip: TPM chip to use.
....@@ -447,14 +545,19 @@
447545 {
448546 int rc;
449547
450
- if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) {
451
- if (chip->flags & TPM_CHIP_FLAG_TPM2)
452
- rc = tpm2_auto_startup(chip);
453
- else
454
- rc = tpm1_auto_startup(chip);
455
- if (rc)
456
- return rc;
548
+ rc = tpm_chip_start(chip);
549
+ if (rc)
550
+ return rc;
551
+ rc = tpm_auto_startup(chip);
552
+ if (rc) {
553
+ tpm_chip_stop(chip);
554
+ return rc;
457555 }
556
+
557
+ rc = tpm_get_pcr_allocation(chip);
558
+ tpm_chip_stop(chip);
559
+ if (rc)
560
+ return rc;
458561
459562 tpm_sysfs_add_device(chip);
460563
....@@ -508,7 +611,7 @@
508611 hwrng_unregister(&chip->hwrng);
509612 tpm_bios_log_teardown(chip);
510613 if (chip->flags & TPM_CHIP_FLAG_TPM2)
511
- cdev_device_del(&chip->cdevs, &chip->devs);
614
+ tpm_devs_remove(chip);
512615 tpm_del_char_device(chip);
513616 }
514617 EXPORT_SYMBOL_GPL(tpm_chip_unregister);