Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bdk/sec/tsec.c
1476 views
1
/*
2
* Copyright (c) 2018 naehrwert
3
* Copyright (c) 2018-2024 CTCaer
4
* Copyright (c) 2018 balika011
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms and conditions of the GNU General Public License,
8
* version 2, as published by the Free Software Foundation.
9
*
10
* This program is distributed in the hope it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
* more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include <string.h>
20
21
#include "tsec.h"
22
#include "tsec_t210.h"
23
#include <memory_map.h>
24
#include <mem/heap.h>
25
#include <mem/mc.h>
26
#include <mem/smmu.h>
27
#include <sec/se_t210.h>
28
#include <soc/bpmp.h>
29
#include <soc/clock.h>
30
#include <soc/kfuse.h>
31
#include <soc/pmc.h>
32
#include <soc/t210.h>
33
#include <soc/timer.h>
34
35
// #include <gfx_utils.h>
36
37
#define PKG11_MAGIC 0x31314B50
38
39
#define TSEC_HOS_KB_620 6
40
41
static int _tsec_dma_wait_idle()
42
{
43
u32 timeout = get_tmr_ms() + 10000;
44
45
while (!(TSEC(TSEC_DMATRFCMD) & TSEC_DMATRFCMD_IDLE))
46
if (get_tmr_ms() > timeout)
47
return 0;
48
49
return 1;
50
}
51
52
static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offset)
53
{
54
u32 cmd;
55
56
if (not_imem)
57
cmd = TSEC_DMATRFCMD_SIZE_256B; // DMA 256 bytes
58
else
59
cmd = TSEC_DMATRFCMD_IMEM; // DMA IMEM (Instruction memmory)
60
61
TSEC(TSEC_DMATRFMOFFS) = i_offset;
62
TSEC(TSEC_DMATRFFBOFFS) = pa_offset;
63
TSEC(TSEC_DMATRFCMD) = cmd;
64
65
return _tsec_dma_wait_idle();
66
}
67
68
int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
69
{
70
int res = 0;
71
u8 *fwbuf = NULL;
72
u32 type = tsec_ctxt->type;
73
u32 *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
74
u32 *pkg11_magic_off;
75
void *ptb;
76
77
bpmp_mmu_disable();
78
bpmp_clk_rate_relaxed(true);
79
80
// Enable clocks.
81
clock_enable_tsec();
82
clock_enable_sor_safe();
83
clock_enable_sor0();
84
clock_enable_sor1();
85
clock_enable_kfuse();
86
kfuse_wait_ready();
87
88
// Disable AHB aperture.
89
mc_disable_ahb_redirect();
90
91
if (type == TSEC_FW_TYPE_NEW)
92
{
93
// Disable all CCPLEX core rails.
94
pmc_enable_partition(POWER_RAIL_CE0, DISABLE);
95
pmc_enable_partition(POWER_RAIL_CE1, DISABLE);
96
pmc_enable_partition(POWER_RAIL_CE2, DISABLE);
97
pmc_enable_partition(POWER_RAIL_CE3, DISABLE);
98
99
// Enable AHB aperture and set it to full mmio.
100
mc_enable_ahb_redirect();
101
}
102
103
// Configure Falcon.
104
TSEC(TSEC_DMACTL) = 0;
105
TSEC(TSEC_IRQMSET) =
106
TSEC_IRQMSET_EXT(0xFF) |
107
TSEC_IRQMSET_WDTMR |
108
TSEC_IRQMSET_HALT |
109
TSEC_IRQMSET_EXTERR |
110
TSEC_IRQMSET_SWGEN0 |
111
TSEC_IRQMSET_SWGEN1;
112
TSEC(TSEC_IRQDEST) =
113
TSEC_IRQDEST_EXT(0xFF) |
114
TSEC_IRQDEST_HALT |
115
TSEC_IRQDEST_EXTERR |
116
TSEC_IRQDEST_SWGEN0 |
117
TSEC_IRQDEST_SWGEN1;
118
TSEC(TSEC_ITFEN) = TSEC_ITFEN_CTXEN | TSEC_ITFEN_MTHDEN;
119
if (!_tsec_dma_wait_idle())
120
{
121
res = -1;
122
goto out;
123
}
124
125
// Load firmware or emulate memio environment for newer TSEC fw.
126
if (type == TSEC_FW_TYPE_EMU)
127
TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8;
128
else
129
{
130
fwbuf = (u8 *)malloc(SZ_16K);
131
u8 *fwbuf_aligned = (u8 *)ALIGN((u32)fwbuf, 0x100);
132
memcpy(fwbuf_aligned, tsec_ctxt->fw, tsec_ctxt->size);
133
134
TSEC(TSEC_DMATRFBASE) = (u32)fwbuf_aligned >> 8;
135
}
136
137
for (u32 addr = 0; addr < tsec_ctxt->size; addr += 0x100)
138
{
139
if (!_tsec_dma_pa_to_internal_100(false, addr, addr))
140
{
141
res = -2;
142
goto out_free;
143
}
144
}
145
146
if (type == TSEC_FW_TYPE_EMU)
147
{
148
// Init SMMU translation for TSEC.
149
ptb = smmu_init_domain(MC_SMMU_TSEC_ASID, 1);
150
smmu_init();
151
152
// Enable SMMU.
153
smmu_enable();
154
155
// Clock reset controller.
156
car = smmu_page_zalloc(1);
157
memcpy(car, (void *)CLOCK_BASE, SZ_PAGE);
158
car[CLK_RST_CONTROLLER_CLK_SOURCE_TSEC / 4] = CLK_SRC_DIV(2);
159
smmu_map(ptb, CLOCK_BASE, (u32)car, 1, SMMU_WRITE | SMMU_READ | SMMU_NS);
160
161
// Fuse driver.
162
fuse = smmu_page_zalloc(1);
163
memcpy((void *)&fuse[0x800/4], (void *)FUSE_BASE, SZ_1K);
164
fuse[0x82C / 4] = 0;
165
fuse[0x9E0 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
166
fuse[0x9E4 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
167
smmu_map(ptb, (FUSE_BASE - 0x800), (u32)fuse, 1, SMMU_READ | SMMU_NS);
168
169
// Power management controller.
170
pmc = smmu_page_zalloc(1);
171
smmu_map(ptb, RTC_BASE, (u32)pmc, 1, SMMU_READ | SMMU_NS);
172
173
// Flow control.
174
flowctrl = smmu_page_zalloc(1);
175
smmu_map(ptb, FLOW_CTLR_BASE, (u32)flowctrl, 1, SMMU_WRITE | SMMU_NS);
176
177
// Security engine.
178
se = smmu_page_zalloc(1);
179
memcpy(se, (void *)SE_BASE, SZ_PAGE);
180
smmu_map(ptb, SE_BASE, (u32)se, 1, SMMU_READ | SMMU_WRITE | SMMU_NS);
181
182
// Memory controller.
183
mc = smmu_page_zalloc(1);
184
memcpy(mc, (void *)MC_BASE, SZ_PAGE);
185
mc[MC_IRAM_BOM / 4] = 0;
186
mc[MC_IRAM_TOM / 4] = DRAM_START;
187
smmu_map(ptb, MC_BASE, (u32)mc, 1, SMMU_READ | SMMU_NS);
188
189
// IRAM
190
iram = smmu_page_zalloc(0x30);
191
memcpy(iram, tsec_ctxt->pkg1, 0x30000);
192
// PKG1.1 magic offset.
193
pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / sizeof(u32)));
194
smmu_map(ptb, 0x40010000, (u32)iram, 0x30, SMMU_READ | SMMU_WRITE | SMMU_NS);
195
196
// Exception vectors
197
evec = smmu_page_zalloc(1);
198
smmu_map(ptb, EXCP_VEC_BASE, (u32)evec, 1, SMMU_READ | SMMU_WRITE | SMMU_NS);
199
}
200
201
// Execute firmware.
202
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
203
TSEC(TSEC_MAILBOX1) = 0;
204
TSEC(TSEC_MAILBOX0) = 1; // Set HOS key version.
205
TSEC(TSEC_BOOTVEC) = 0;
206
TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU;
207
208
if (type == TSEC_FW_TYPE_EMU)
209
{
210
u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
211
u32 timeout = get_tmr_us() + 125000;
212
u32 key[16] = {0};
213
u32 kidx = 0;
214
215
while (*pkg11_magic_off != PKG11_MAGIC)
216
{
217
smmu_flush_all();
218
219
if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
220
{
221
k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
222
key[kidx++] = k;
223
}
224
225
// Failsafe.
226
if ((u32)get_tmr_us() > timeout)
227
break;
228
}
229
230
if (kidx != 8)
231
{
232
res = -6;
233
smmu_deinit_domain(MC_SMMU_TSEC_ASID, 1);
234
235
goto out_free;
236
}
237
238
// Give some extra time to make sure PKG1.1 is decrypted.
239
msleep(50);
240
241
memcpy(tsec_keys, &key, 0x20);
242
memcpy(tsec_ctxt->pkg1, iram, 0x30000);
243
244
smmu_deinit_domain(MC_SMMU_TSEC_ASID, 1);
245
246
// for (int i = 0; i < kidx; i++)
247
// gfx_printf("key %08X\n", key[i]);
248
249
// gfx_printf("cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_MAILBOX1));
250
251
// u32 errst = MC(MC_ERR_STATUS);
252
// gfx_printf(" MC %08X %08X %08X\n", MC(MC_INTSTATUS), errst, MC(MC_ERR_ADR));
253
// gfx_printf(" type: %02X\n", errst >> 28);
254
// gfx_printf(" smmu: %02X\n", (errst >> 25) & 3);
255
// gfx_printf(" dir: %s\n", (errst >> 16) & 1 ? "W" : "R");
256
// gfx_printf(" cid: %02x\n", errst & 0xFF);
257
}
258
else
259
{
260
if (!_tsec_dma_wait_idle())
261
{
262
res = -3;
263
goto out_free;
264
}
265
266
u32 timeout = get_tmr_ms() + 2000;
267
while (!TSEC(TSEC_MAILBOX1))
268
{
269
if (get_tmr_ms() > timeout)
270
{
271
res = -4;
272
goto out_free;
273
}
274
}
275
276
if (TSEC(TSEC_MAILBOX1) != 0xB0B0B0B0)
277
{
278
res = -5;
279
goto out_free;
280
}
281
282
// Fetch result.
283
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
284
u32 buf[4];
285
buf[0] = SOR1(SOR_DP_HDCP_BKSV_LSB);
286
buf[1] = SOR1(SOR_TMDS_HDCP_BKSV_LSB);
287
buf[2] = SOR1(SOR_TMDS_HDCP_CN_MSB);
288
buf[3] = SOR1(SOR_TMDS_HDCP_CN_LSB);
289
SOR1(SOR_DP_HDCP_BKSV_LSB) = 0;
290
SOR1(SOR_TMDS_HDCP_BKSV_LSB) = 0;
291
SOR1(SOR_TMDS_HDCP_CN_MSB) = 0;
292
SOR1(SOR_TMDS_HDCP_CN_LSB) = 0;
293
294
memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
295
}
296
297
out_free:
298
free(fwbuf);
299
300
out:
301
// Disable clocks.
302
clock_disable_kfuse();
303
clock_disable_sor1();
304
clock_disable_sor0();
305
clock_disable_sor_safe();
306
clock_disable_tsec();
307
bpmp_mmu_enable();
308
bpmp_clk_rate_relaxed(false);
309
310
#ifdef BDK_MC_ENABLE_AHB_REDIRECT
311
// Re-enable AHB aperture.
312
mc_enable_ahb_redirect();
313
#endif
314
315
return res;
316
}
317
318