blob: 23236ff5551f33d0b0b76898baeaff69f2f119fe [file] [log] [blame]
Patrick Rudolphd8d8be12020-09-21 09:48:53 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <types.h>
Patrick Rudolphd8d8be12020-09-21 09:48:53 +02004#include <acpi/acpi.h>
5#include <acpi/acpigen.h>
6#include <acpi/acpi_device.h>
7
8#include "tpm_ppi.h"
9
10static void tpm_ppi_func0_cb(void *arg)
11{
12 /* Functions 1-8. */
13 u8 buf[] = {0xff, 0x01};
14 acpigen_write_return_byte_buffer(buf, sizeof(buf));
15}
16
17static void tpm_ppi_func1_cb(void *arg)
18{
19 if (CONFIG(TPM2))
Patrick Rudolph2bea58d2020-09-21 10:27:40 +020020 /* Interface version: 1.3 */
21 acpigen_write_return_string("1.3");
Patrick Rudolphd8d8be12020-09-21 09:48:53 +020022 else
23 /* Interface version: 1.2 */
24 acpigen_write_return_string("1.2");
25}
26
27static void tpm_ppi_func2_cb(void *arg)
28{
29 /* Submit operations: drop on the floor and return success. */
30 acpigen_write_return_byte(PPI2_RET_SUCCESS);
31}
32
33static void tpm_ppi_func3_cb(void *arg)
34{
35 /* Pending operation: none. */
36 acpigen_emit_byte(RETURN_OP);
37 acpigen_write_package(2);
38 acpigen_write_byte(0);
39 acpigen_write_byte(0);
40 acpigen_pop_len();
41}
42
43static void tpm_ppi_func4_cb(void *arg)
44{
45 /* Pre-OS transition method: reboot. */
46 acpigen_write_return_byte(2);
47}
48
49static void tpm_ppi_func5_cb(void *arg)
50{
51 /* Operation response: no operation executed. */
52 acpigen_emit_byte(RETURN_OP);
53 acpigen_write_package(3);
54 acpigen_write_byte(0);
55 acpigen_write_byte(0);
56 acpigen_write_byte(0);
57 acpigen_pop_len();
58}
59
60static void tpm_ppi_func6_cb(void *arg)
61{
62 /*
63 * Set preferred user language: deprecated and must return 3 AKA
64 * "not implemented".
65 */
66 acpigen_write_return_byte(PPI6_RET_NOT_IMPLEMENTED);
67}
68
69static void tpm_ppi_func7_cb(void *arg)
70{
71 /* Submit operations: deny. */
72 acpigen_write_return_byte(PPI7_RET_BLOCKED_BY_FIRMWARE);
73}
74
75static void tpm_ppi_func8_cb(void *arg)
76{
77 /* All actions are forbidden. */
78 acpigen_write_return_byte(PPI8_RET_FIRMWARE_ONLY);
79}
80
81static void (*tpm_ppi_callbacks[])(void *) = {
82 tpm_ppi_func0_cb,
83 tpm_ppi_func1_cb,
84 tpm_ppi_func2_cb,
85 tpm_ppi_func3_cb,
86 tpm_ppi_func4_cb,
87 tpm_ppi_func5_cb,
88 tpm_ppi_func6_cb,
89 tpm_ppi_func7_cb,
90 tpm_ppi_func8_cb,
91};
92
93static void tpm_mci_func0_cb(void *arg)
94{
95 /* Function 1. */
96 acpigen_write_return_singleton_buffer(0x3);
97}
98static void tpm_mci_func1_cb(void *arg)
99{
100 /* Just return success. */
101 acpigen_write_return_byte(0);
102}
103
104static void (*tpm_mci_callbacks[])(void *) = {
105 tpm_mci_func0_cb,
106 tpm_mci_func1_cb,
107};
108
109void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
110{
111 /*
112 * _DSM method
113 */
114 struct dsm_uuid ids[] = {
115 /* Physical presence interface.
116 * This is used to submit commands like "Clear TPM" to
117 * be run at next reboot provided that user confirms
118 * them. Spec allows user to cancel all commands and/or
119 * configure BIOS to reject commands. So we pretend that
120 * user did just this: cancelled everything. If user
121 * really wants to clear TPM the only option now is to
122 * do it manually in payload.
123 */
124 DSM_UUID(TPM_PPI_UUID, tpm_ppi_callbacks,
125 ARRAY_SIZE(tpm_ppi_callbacks), NULL),
126 /* Memory clearing on boot: just a dummy. */
127 DSM_UUID(TPM_MCI_UUID, tpm_mci_callbacks,
128 ARRAY_SIZE(tpm_mci_callbacks), NULL),
129 };
130
131 acpigen_write_dsm_uuid_arr(ids, ARRAY_SIZE(ids));
132}