blob: c878743feeb0dba3536d1aefdea60078ed579ed6 [file] [log] [blame]
Peng Fanf1e0f9f2019-09-25 08:11:14 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2018-2019 NXP
4 */
5
6#include <common.h>
Simon Glassed38aef2020-05-10 11:40:03 -06007#include <command.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +00008#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060010#include <asm/global_data.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +000011#include <asm/io.h>
Peng Fan2e0644a2023-04-28 12:08:09 +080012#include <firmware/imx/sci/sci.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +000013#include <asm/mach-imx/sys_proto.h>
14#include <asm/arch-imx/cpu.h>
15#include <asm/arch/sys_proto.h>
Ye Lieb101272021-08-07 16:00:37 +080016#include <asm/mach-imx/image.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +000017#include <console.h>
Oliver Grautef46161a2020-11-06 09:09:29 +010018#include <cpu_func.h>
Ye Li185af302023-06-15 18:09:23 +080019#include <asm/mach-imx/ahab.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +000020
21DECLARE_GLOBAL_DATA_PTR;
22
23#define SEC_SECURE_RAM_BASE (0x31800000UL)
24#define SEC_SECURE_RAM_END_BASE (SEC_SECURE_RAM_BASE + 0xFFFFUL)
25#define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE (0x60000000UL)
26
27#define SECO_PT 2U
28
Ye Li185af302023-06-15 18:09:23 +080029int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length)
30{
31 int err;
32
33 memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)container,
34 ALIGN(length, CONFIG_SYS_CACHELINE_SIZE));
35
36 err = sc_seco_authenticate(-1, SC_SECO_AUTH_CONTAINER,
37 SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE);
38 if (err)
39 printf("Authenticate container hdr failed, return %d\n", err);
40
41 return err;
42}
43
44int ahab_auth_release(void)
45{
46 int err;
47
48 err = sc_seco_authenticate(-1, SC_SECO_REL_CONTAINER, 0);
49 if (err)
50 printf("Error: release container failed!\n");
51
52 return err;
53}
54
55int ahab_verify_cntr_image(struct boot_img_t *img, int image_index)
56{
57 sc_faddr_t start, end;
58 sc_rm_mr_t mr;
59 int err;
60 int ret = 0;
61
62 debug("img %d, dst 0x%llx, src 0x%x, size 0x%x\n",
63 image_index, img->dst, img->offset, img->size);
64
65 /* Find the memreg and set permission for seco pt */
66 err = sc_rm_find_memreg(-1, &mr,
67 img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1),
68 ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE) - 1);
69
70 if (err) {
71 printf("Error: can't find memreg for image load address 0x%llx, error %d\n",
72 img->dst, err);
73 return -ENOMEM;
74 }
75
76 err = sc_rm_get_memreg_info(-1, mr, &start, &end);
77 if (!err)
78 debug("memreg %u 0x%llx -- 0x%llx\n", mr, start, end);
79
80 err = sc_rm_set_memreg_permissions(-1, mr,
81 SECO_PT, SC_RM_PERM_FULL);
82 if (err) {
83 printf("Set permission failed for img %d, error %d\n",
84 image_index, err);
85 return -EPERM;
86 }
87
88 err = sc_seco_authenticate(-1, SC_SECO_VERIFY_IMAGE,
89 1 << image_index);
90 if (err) {
91 printf("Authenticate img %d failed, return %d\n",
92 image_index, err);
93 ret = -EIO;
94 }
95
96 err = sc_rm_set_memreg_permissions(-1, mr,
97 SECO_PT, SC_RM_PERM_NONE);
98 if (err) {
99 printf("Remove permission failed for img %d, error %d\n",
100 image_index, err);
101 ret = -EPERM;
102 }
103
104 return ret;
105}
106
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000107static inline bool check_in_dram(ulong addr)
108{
109 int i;
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900110 struct bd_info *bd = gd->bd;
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000111
112 for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
113 if (bd->bi_dram[i].size) {
114 if (addr >= bd->bi_dram[i].start &&
115 addr < (bd->bi_dram[i].start + bd->bi_dram[i].size))
116 return true;
117 }
118 }
119
120 return false;
121}
122
123int authenticate_os_container(ulong addr)
124{
125 struct container_hdr *phdr;
126 int i, ret = 0;
127 int err;
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000128 u16 length;
129 struct boot_img_t *img;
130 unsigned long s, e;
131
132 if (addr % 4) {
133 puts("Error: Image's address is not 4 byte aligned\n");
134 return -EINVAL;
135 }
136
137 if (!check_in_dram(addr)) {
138 puts("Error: Image's address is invalid\n");
139 return -EINVAL;
140 }
141
142 phdr = (struct container_hdr *)addr;
143 if (phdr->tag != 0x87 && phdr->version != 0x0) {
144 printf("Error: Wrong container header\n");
145 return -EFAULT;
146 }
147
148 if (!phdr->num_images) {
149 printf("Error: Wrong container, no image found\n");
150 return -EFAULT;
151 }
152
153 length = phdr->length_lsb + (phdr->length_msb << 8);
154
155 debug("container length %u\n", length);
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000156
Ye Li185af302023-06-15 18:09:23 +0800157 err = ahab_auth_cntr_hdr(phdr, length);
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000158 if (err) {
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000159 ret = -EIO;
160 goto exit;
161 }
162
163 /* Copy images to dest address */
164 for (i = 0; i < phdr->num_images; i++) {
165 img = (struct boot_img_t *)(addr +
166 sizeof(struct container_hdr) +
167 i * sizeof(struct boot_img_t));
168
Oliver Graute8ad653b2020-11-06 09:09:30 +0100169 debug("img %d, dst 0x%x, src 0x%lux, size 0x%x\n",
Seb Fagardc307ad02020-03-30 17:13:31 +0200170 i, (uint32_t) img->dst, img->offset + addr, img->size);
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000171
172 memcpy((void *)img->dst, (const void *)(img->offset + addr),
173 img->size);
174
175 s = img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
Peng Fan194dccc2020-04-22 15:36:34 +0800176 e = ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE) - 1;
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000177
178 flush_dcache_range(s, e);
179
Ye Li185af302023-06-15 18:09:23 +0800180 ret = ahab_verify_cntr_image(img, i);
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000181 if (ret)
182 goto exit;
183 }
184
185exit:
Ye Li185af302023-06-15 18:09:23 +0800186 ahab_auth_release();
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000187
188 return ret;
189}
190
Simon Glassed38aef2020-05-10 11:40:03 -0600191static int do_authenticate(struct cmd_tbl *cmdtp, int flag, int argc,
192 char *const argv[])
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000193{
194 ulong addr;
195
196 if (argc < 2)
197 return CMD_RET_USAGE;
198
Simon Glass3ff49ec2021-07-24 09:03:29 -0600199 addr = hextoul(argv[1], NULL);
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000200
201 printf("Authenticate OS container at 0x%lx\n", addr);
202
203 if (authenticate_os_container(addr))
204 return CMD_RET_FAILURE;
205
206 return CMD_RET_SUCCESS;
207}
208
209static void display_life_cycle(u16 lc)
210{
211 printf("Lifecycle: 0x%04X, ", lc);
212 switch (lc) {
213 case 0x1:
214 printf("Pristine\n\n");
215 break;
216 case 0x2:
217 printf("Fab\n\n");
218 break;
219 case 0x8:
220 printf("Open\n\n");
221 break;
222 case 0x20:
223 printf("NXP closed\n\n");
224 break;
225 case 0x80:
226 printf("OEM closed\n\n");
227 break;
228 case 0x100:
229 printf("Partial field return\n\n");
230 break;
231 case 0x200:
232 printf("Full field return\n\n");
233 break;
234 case 0x400:
235 printf("No return\n\n");
236 break;
237 default:
238 printf("Unknown\n\n");
239 break;
240 }
241}
242
243#define AHAB_AUTH_CONTAINER_REQ 0x87
244#define AHAB_VERIFY_IMAGE_REQ 0x88
245
246#define AHAB_NO_AUTHENTICATION_IND 0xee
247#define AHAB_BAD_KEY_HASH_IND 0xfa
248#define AHAB_INVALID_KEY_IND 0xf9
249#define AHAB_BAD_SIGNATURE_IND 0xf0
250#define AHAB_BAD_HASH_IND 0xf1
251
252static void display_ahab_auth_event(u32 event)
253{
254 u8 cmd = (event >> 16) & 0xff;
255 u8 resp_ind = (event >> 8) & 0xff;
256
257 switch (cmd) {
258 case AHAB_AUTH_CONTAINER_REQ:
259 printf("\tCMD = AHAB_AUTH_CONTAINER_REQ (0x%02X)\n", cmd);
260 printf("\tIND = ");
261 break;
262 case AHAB_VERIFY_IMAGE_REQ:
263 printf("\tCMD = AHAB_VERIFY_IMAGE_REQ (0x%02X)\n", cmd);
264 printf("\tIND = ");
265 break;
266 default:
267 return;
268 }
269
270 switch (resp_ind) {
271 case AHAB_NO_AUTHENTICATION_IND:
272 printf("AHAB_NO_AUTHENTICATION_IND (0x%02X)\n\n", resp_ind);
273 break;
274 case AHAB_BAD_KEY_HASH_IND:
275 printf("AHAB_BAD_KEY_HASH_IND (0x%02X)\n\n", resp_ind);
276 break;
277 case AHAB_INVALID_KEY_IND:
278 printf("AHAB_INVALID_KEY_IND (0x%02X)\n\n", resp_ind);
279 break;
280 case AHAB_BAD_SIGNATURE_IND:
281 printf("AHAB_BAD_SIGNATURE_IND (0x%02X)\n\n", resp_ind);
282 break;
283 case AHAB_BAD_HASH_IND:
284 printf("AHAB_BAD_HASH_IND (0x%02X)\n\n", resp_ind);
285 break;
286 default:
287 printf("Unknown Indicator (0x%02X)\n\n", resp_ind);
288 break;
289 }
290}
291
Simon Glassed38aef2020-05-10 11:40:03 -0600292static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc,
293 char *const argv[])
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000294{
295 int err;
296 u8 idx = 0U;
297 u32 event;
298 u16 lc;
299
300 err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
Peng Fan25b7eb42023-06-15 18:08:58 +0800301 if (err) {
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000302 printf("Error in get lifecycle\n");
303 return -EIO;
304 }
305
306 display_life_cycle(lc);
307
308 err = sc_seco_get_event(-1, idx, &event);
Peng Fan25b7eb42023-06-15 18:08:58 +0800309 while (!err) {
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000310 printf("SECO Event[%u] = 0x%08X\n", idx, event);
311 display_ahab_auth_event(event);
312
313 idx++;
314 err = sc_seco_get_event(-1, idx, &event);
315 }
316
317 if (idx == 0)
318 printf("No SECO Events Found!\n\n");
319
320 return 0;
321}
322
323static int confirm_close(void)
324{
325 puts("Warning: Please ensure your sample is in NXP closed state, "
326 "OEM SRK hash has been fused, \n"
327 " and you are able to boot a signed image successfully "
328 "without any SECO events reported.\n"
329 " If not, your sample will be unrecoverable.\n"
330 "\nReally perform this operation? <y/N>\n");
331
332 if (confirm_yesno())
333 return 1;
334
335 puts("Ahab close aborted\n");
336 return 0;
337}
338
Simon Glassed38aef2020-05-10 11:40:03 -0600339static int do_ahab_close(struct cmd_tbl *cmdtp, int flag, int argc,
340 char *const argv[])
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000341{
Clément Pérone61e6bc2020-12-21 18:31:28 +0100342 int confirmed = argc >= 2 && !strcmp(argv[1], "-y");
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000343 int err;
344 u16 lc;
345
Clément Pérone61e6bc2020-12-21 18:31:28 +0100346 if (!confirmed && !confirm_close())
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000347 return -EACCES;
348
349 err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
Peng Fan25b7eb42023-06-15 18:08:58 +0800350 if (err) {
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000351 printf("Error in get lifecycle\n");
352 return -EIO;
353 }
354
355 if (lc != 0x20) {
356 puts("Current lifecycle is NOT NXP closed, can't move to OEM closed\n");
357 display_life_cycle(lc);
358 return -EPERM;
359 }
360
361 err = sc_seco_forward_lifecycle(-1, 16);
Peng Fan25b7eb42023-06-15 18:08:58 +0800362 if (err) {
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000363 printf("Error in forward lifecycle to OEM closed\n");
364 return -EIO;
365 }
366
367 printf("Change to OEM closed successfully\n");
368
369 return 0;
370}
371
372U_BOOT_CMD(auth_cntr, CONFIG_SYS_MAXARGS, 1, do_authenticate,
373 "autenticate OS container via AHAB",
374 "addr\n"
375 "addr - OS container hex address\n"
376);
377
378U_BOOT_CMD(ahab_status, CONFIG_SYS_MAXARGS, 1, do_ahab_status,
379 "display AHAB lifecycle and events from seco",
380 ""
381);
382
383U_BOOT_CMD(ahab_close, CONFIG_SYS_MAXARGS, 1, do_ahab_close,
384 "Change AHAB lifecycle to OEM closed",
385 ""
386);