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