14
15
#include "qemu/osdep.h"
16
#include <glib/gstdio.h>
17
+#include "qemu/bswap.h"
18
19
#include "hw/acpi/tpm.h"
20
#include "libqtest.h"
21
#include "tpm-util.h"
22
#include "qobject/qdict.h"
23
24
+#define CRB_ADDR_START (TPM_CRB_ADDR_BASE + A_CRB_CTRL_START)
25
+#define CRB_ADDR_CTRL_STS (TPM_CRB_ADDR_BASE + A_CRB_CTRL_STS)
26
+#define CRB_ADDR_CTRL_CMD_SIZE \
27
+ (TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE)
28
+
29
+#define CRB_START_INVOKE (1 << 0)
30
+#define CRB_START_RSP_RETRY (1 << 1)
31
+#define CRB_START_NEXT_CHUNK (1 << 2)
32
+
33
+void tpm_wait_till_bit_clear(QTestState *s, uint64_t addr, uint32_t mask)
34
+{
35
+ uint32_t sts;
36
+ uint64_t end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
37
+
38
+ while (true) {
39
+ sts = qtest_readl(s, addr);
40
+ if ((sts & mask) == 0) {
41
+ break;
42
+ }
43
+ if (g_get_monotonic_time() >= end_time) {
44
+ g_assert_cmphex(sts & mask, ==, 0);
45
+ break;
46
+ }
47
+ }
48
+}
49
+
50
void tpm_util_crb_transfer(QTestState *s,
51
const unsigned char *req, size_t req_size,
52
unsigned char *rsp, size_t rsp_size)
53
{
54
+ uint32_t tpm_sts;
55
uint64_t caddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
56
uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
57
59
60
qtest_memwrite(s, caddr, req, req_size);
61
34
- uint32_t sts, start = 1;
35
- uint64_t end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
36
- qtest_writel(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_START, start);
37
- while (true) {
38
- start = qtest_readl(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_START);
39
- if ((start & 1) == 0) {
40
- break;
62
+ qtest_writel(s, CRB_ADDR_START, CRB_START_INVOKE);
63
+ tpm_wait_till_bit_clear(s, CRB_ADDR_START, CRB_START_INVOKE);
64
+
65
+ tpm_sts = qtest_readl(s, CRB_ADDR_CTRL_STS);
66
+ g_assert_cmpint(tpm_sts & 1, ==, 0);
67
+
68
+ qtest_memread(s, raddr, rsp, rsp_size);
69
+}
70
+
71
+void tpm_util_crb_chunk_transfer(QTestState *s,
72
+ const unsigned char *req, size_t req_size,
73
+ unsigned char *rsp, size_t rsp_size)
74
+{
75
+ uint32_t tpm_sts;
76
+ size_t chunk_size;
77
+ unsigned char header[10];
78
+ uint32_t actual_response_size = 0;
79
+
80
+ uint64_t caddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
81
+ uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
82
+ uint32_t crb_ctrl_cmd_size = qtest_readl(s, CRB_ADDR_CTRL_CMD_SIZE);
83
+
84
+ chunk_size = crb_ctrl_cmd_size;
85
+
86
+ qtest_writeb(s, TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL, 1);
87
+
88
+ for (size_t i = 0; i < req_size; i += chunk_size) {
89
+ bool last_chunk = false;
90
+ size_t current_chunk_size = chunk_size;
91
+
92
+ if (i + chunk_size > req_size) {
93
+ last_chunk = true;
94
+ current_chunk_size = req_size - i;
95
}
42
- if (g_get_monotonic_time() >= end_time) {
43
- break;
96
+
97
+ qtest_memwrite(s, caddr, req + i, current_chunk_size);
98
+
99
+ if (last_chunk) {
100
+ qtest_writel(s, CRB_ADDR_START, CRB_START_INVOKE);
101
+ tpm_wait_till_bit_clear(s, CRB_ADDR_START, CRB_START_INVOKE);
102
+ } else {
103
+ qtest_writel(s, CRB_ADDR_START, CRB_START_NEXT_CHUNK);
104
+ tpm_wait_till_bit_clear(s, CRB_ADDR_START, CRB_START_NEXT_CHUNK);
105
}
45
- };
46
- start = qtest_readl(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_START);
47
- g_assert_cmpint(start & 1, ==, 0);
48
- sts = qtest_readl(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_STS);
49
- g_assert_cmpint(sts & 1, ==, 0);
106
+ }
107
+ tpm_sts = qtest_readl(s, CRB_ADDR_CTRL_STS);
108
+ g_assert_cmpint(tpm_sts & 1, ==, 0);
109
51
- qtest_memread(s, raddr, rsp, rsp_size);
110
+ /*
111
+ * Read response in chunks
112
+ */
113
+
114
+ qtest_memread(s, raddr, header, sizeof(header));
115
+ actual_response_size = ldl_be_p(&header[2]);
116
+
117
+ if (actual_response_size > rsp_size) {
118
+ actual_response_size = rsp_size;
119
+ }
120
+
121
+ for (size_t i = 0; i < actual_response_size; i += chunk_size) {
122
+ size_t to_read = i + chunk_size > actual_response_size
123
+ ? actual_response_size - i
124
+ : chunk_size;
125
+ if (i > 0) {
126
+ qtest_writel(s, CRB_ADDR_START, CRB_START_NEXT_CHUNK);
127
+ tpm_wait_till_bit_clear(s, CRB_ADDR_START, CRB_START_NEXT_CHUNK);
128
+ }
129
+ qtest_memread(s, raddr, rsp + i, to_read);
130
+ }
131
}
132
133
void tpm_util_startup(QTestState *s, tx_func *tx)