armv7/ls102xa: Fix non-boot cpus cannot correctly fall in spin table
[oweals/u-boot.git] / arch / arm / cpu / armv7 / mx6 / hab.c
1 /*
2  * Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:    GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <asm/io.h>
9 #include <asm/system.h>
10 #include <asm/arch/hab.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/sys_proto.h>
13
14 /* -------- start of HAB API updates ------------*/
15
16 #define hab_rvt_report_event_p                                  \
17 (                                                               \
18         ((is_cpu_type(MXC_CPU_MX6Q) ||                          \
19           is_cpu_type(MXC_CPU_MX6D)) &&                         \
20           (soc_rev() >= CHIP_REV_1_5)) ?                        \
21         ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) :  \
22         (is_cpu_type(MXC_CPU_MX6DL) &&                          \
23          (soc_rev() >= CHIP_REV_1_2)) ?                         \
24         ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) :  \
25         ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT)        \
26 )
27
28 #define hab_rvt_report_status_p                                 \
29 (                                                               \
30         ((is_cpu_type(MXC_CPU_MX6Q) ||                          \
31           is_cpu_type(MXC_CPU_MX6D)) &&                         \
32           (soc_rev() >= CHIP_REV_1_5)) ?                        \
33         ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\
34         (is_cpu_type(MXC_CPU_MX6DL) &&                          \
35          (soc_rev() >= CHIP_REV_1_2)) ?                         \
36         ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\
37         ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS)      \
38 )
39
40 #define hab_rvt_authenticate_image_p                            \
41 (                                                               \
42         ((is_cpu_type(MXC_CPU_MX6Q) ||                          \
43           is_cpu_type(MXC_CPU_MX6D)) &&                         \
44           (soc_rev() >= CHIP_REV_1_5)) ?                        \
45         ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \
46         (is_cpu_type(MXC_CPU_MX6DL) &&                          \
47          (soc_rev() >= CHIP_REV_1_2)) ?                         \
48         ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \
49         ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE)    \
50 )
51
52 #define hab_rvt_entry_p                                         \
53 (                                                               \
54         ((is_cpu_type(MXC_CPU_MX6Q) ||                          \
55           is_cpu_type(MXC_CPU_MX6D)) &&                         \
56           (soc_rev() >= CHIP_REV_1_5)) ?                        \
57         ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) :                \
58         (is_cpu_type(MXC_CPU_MX6DL) &&                          \
59          (soc_rev() >= CHIP_REV_1_2)) ?                         \
60         ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) :                \
61         ((hab_rvt_entry_t *)HAB_RVT_ENTRY)                      \
62 )
63
64 #define hab_rvt_exit_p                                          \
65 (                                                               \
66         ((is_cpu_type(MXC_CPU_MX6Q) ||                          \
67           is_cpu_type(MXC_CPU_MX6D)) &&                         \
68           (soc_rev() >= CHIP_REV_1_5)) ?                        \
69         ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) :                  \
70         (is_cpu_type(MXC_CPU_MX6DL) &&                          \
71          (soc_rev() >= CHIP_REV_1_2)) ?                         \
72         ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) :                  \
73         ((hab_rvt_exit_t *)HAB_RVT_EXIT)                        \
74 )
75
76 #define IVT_SIZE                0x20
77 #define ALIGN_SIZE              0x1000
78 #define CSF_PAD_SIZE            0x2000
79 #define MX6DQ_PU_IROM_MMU_EN_VAR        0x009024a8
80 #define MX6DLS_PU_IROM_MMU_EN_VAR       0x00901dd0
81 #define MX6SL_PU_IROM_MMU_EN_VAR        0x00900a18
82
83 /*
84  * +------------+  0x0 (DDR_UIMAGE_START) -
85  * |   Header   |                          |
86  * +------------+  0x40                    |
87  * |            |                          |
88  * |            |                          |
89  * |            |                          |
90  * |            |                          |
91  * | Image Data |                          |
92  * .            |                          |
93  * .            |                           > Stuff to be authenticated ----+
94  * .            |                          |                                |
95  * |            |                          |                                |
96  * |            |                          |                                |
97  * +------------+                          |                                |
98  * |            |                          |                                |
99  * | Fill Data  |                          |                                |
100  * |            |                          |                                |
101  * +------------+ Align to ALIGN_SIZE      |                                |
102  * |    IVT     |                          |                                |
103  * +------------+ + IVT_SIZE              -                                 |
104  * |            |                                                           |
105  * |  CSF DATA  | <---------------------------------------------------------+
106  * |            |
107  * +------------+
108  * |            |
109  * | Fill Data  |
110  * |            |
111  * +------------+ + CSF_PAD_SIZE
112  */
113
114 #define MAX_RECORD_BYTES     (8*1024) /* 4 kbytes */
115
116 struct record {
117         uint8_t  tag;                                           /* Tag */
118         uint8_t  len[2];                                        /* Length */
119         uint8_t  par;                                           /* Version */
120         uint8_t  contents[MAX_RECORD_BYTES];/* Record Data */
121         bool     any_rec_flag;
122 };
123
124 char *rsn_str[] = {"RSN = HAB_RSN_ANY (0x00)\n",
125                                    "RSN = HAB_ENG_FAIL (0x30)\n",
126                                    "RSN = HAB_INV_ADDRESS (0x22)\n",
127                                    "RSN = HAB_INV_ASSERTION (0x0C)\n",
128                                    "RSN = HAB_INV_CALL (0x28)\n",
129                                    "RSN = HAB_INV_CERTIFICATE (0x21)\n",
130                                    "RSN = HAB_INV_COMMAND (0x06)\n",
131                                    "RSN = HAB_INV_CSF (0x11)\n",
132                                    "RSN = HAB_INV_DCD (0x27)\n",
133                                    "RSN = HAB_INV_INDEX (0x0F)\n",
134                                    "RSN = HAB_INV_IVT (0x05)\n",
135                                    "RSN = HAB_INV_KEY (0x1D)\n",
136                                    "RSN = HAB_INV_RETURN (0x1E)\n",
137                                    "RSN = HAB_INV_SIGNATURE (0x18)\n",
138                                    "RSN = HAB_INV_SIZE (0x17)\n",
139                                    "RSN = HAB_MEM_FAIL (0x2E)\n",
140                                    "RSN = HAB_OVR_COUNT (0x2B)\n",
141                                    "RSN = HAB_OVR_STORAGE (0x2D)\n",
142                                    "RSN = HAB_UNS_ALGORITHM (0x12)\n",
143                                    "RSN = HAB_UNS_COMMAND (0x03)\n",
144                                    "RSN = HAB_UNS_ENGINE (0x0A)\n",
145                                    "RSN = HAB_UNS_ITEM (0x24)\n",
146                                    "RSN = HAB_UNS_KEY (0x1B)\n",
147                                    "RSN = HAB_UNS_PROTOCOL (0x14)\n",
148                                    "RSN = HAB_UNS_STATE (0x09)\n",
149                                    "RSN = INVALID\n",
150                                    NULL};
151
152 char *sts_str[] = {"STS = HAB_SUCCESS (0xF0)\n",
153                                    "STS = HAB_FAILURE (0x33)\n",
154                                    "STS = HAB_WARNING (0x69)\n",
155                                    "STS = INVALID\n",
156                                    NULL};
157
158 char *eng_str[] = {"ENG = HAB_ENG_ANY (0x00)\n",
159                                    "ENG = HAB_ENG_SCC (0x03)\n",
160                                    "ENG = HAB_ENG_RTIC (0x05)\n",
161                                    "ENG = HAB_ENG_SAHARA (0x06)\n",
162                                    "ENG = HAB_ENG_CSU (0x0A)\n",
163                                    "ENG = HAB_ENG_SRTC (0x0C)\n",
164                                    "ENG = HAB_ENG_DCP (0x1B)\n",
165                                    "ENG = HAB_ENG_CAAM (0x1D)\n",
166                                    "ENG = HAB_ENG_SNVS (0x1E)\n",
167                                    "ENG = HAB_ENG_OCOTP (0x21)\n",
168                                    "ENG = HAB_ENG_DTCP (0x22)\n",
169                                    "ENG = HAB_ENG_ROM (0x36)\n",
170                                    "ENG = HAB_ENG_HDCP (0x24)\n",
171                                    "ENG = HAB_ENG_RTL (0x77)\n",
172                                    "ENG = HAB_ENG_SW (0xFF)\n",
173                                    "ENG = INVALID\n",
174                                    NULL};
175
176 char *ctx_str[] = {"CTX = HAB_CTX_ANY(0x00)\n",
177                                    "CTX = HAB_CTX_FAB (0xFF)\n",
178                                    "CTX = HAB_CTX_ENTRY (0xE1)\n",
179                                    "CTX = HAB_CTX_TARGET (0x33)\n",
180                                    "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
181                                    "CTX = HAB_CTX_DCD (0xDD)\n",
182                                    "CTX = HAB_CTX_CSF (0xCF)\n",
183                                    "CTX = HAB_CTX_COMMAND (0xC0)\n",
184                                    "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
185                                    "CTX = HAB_CTX_ASSERT (0xA0)\n",
186                                    "CTX = HAB_CTX_EXIT (0xEE)\n",
187                                    "CTX = INVALID\n",
188                                    NULL};
189
190 uint8_t hab_statuses[5] = {
191         HAB_STS_ANY,
192         HAB_FAILURE,
193         HAB_WARNING,
194         HAB_SUCCESS,
195         -1
196 };
197
198 uint8_t hab_reasons[26] = {
199         HAB_RSN_ANY,
200         HAB_ENG_FAIL,
201         HAB_INV_ADDRESS,
202         HAB_INV_ASSERTION,
203         HAB_INV_CALL,
204         HAB_INV_CERTIFICATE,
205         HAB_INV_COMMAND,
206         HAB_INV_CSF,
207         HAB_INV_DCD,
208         HAB_INV_INDEX,
209         HAB_INV_IVT,
210         HAB_INV_KEY,
211         HAB_INV_RETURN,
212         HAB_INV_SIGNATURE,
213         HAB_INV_SIZE,
214         HAB_MEM_FAIL,
215         HAB_OVR_COUNT,
216         HAB_OVR_STORAGE,
217         HAB_UNS_ALGORITHM,
218         HAB_UNS_COMMAND,
219         HAB_UNS_ENGINE,
220         HAB_UNS_ITEM,
221         HAB_UNS_KEY,
222         HAB_UNS_PROTOCOL,
223         HAB_UNS_STATE,
224         -1
225 };
226
227 uint8_t hab_contexts[12] = {
228         HAB_CTX_ANY,
229         HAB_CTX_FAB,
230         HAB_CTX_ENTRY,
231         HAB_CTX_TARGET,
232         HAB_CTX_AUTHENTICATE,
233         HAB_CTX_DCD,
234         HAB_CTX_CSF,
235         HAB_CTX_COMMAND,
236         HAB_CTX_AUT_DAT,
237         HAB_CTX_ASSERT,
238         HAB_CTX_EXIT,
239         -1
240 };
241
242 uint8_t hab_engines[16] = {
243         HAB_ENG_ANY,
244         HAB_ENG_SCC,
245         HAB_ENG_RTIC,
246         HAB_ENG_SAHARA,
247         HAB_ENG_CSU,
248         HAB_ENG_SRTC,
249         HAB_ENG_DCP,
250         HAB_ENG_CAAM,
251         HAB_ENG_SNVS,
252         HAB_ENG_OCOTP,
253         HAB_ENG_DTCP,
254         HAB_ENG_ROM,
255         HAB_ENG_HDCP,
256         HAB_ENG_RTL,
257         HAB_ENG_SW,
258         -1
259 };
260
261 bool is_hab_enabled(void)
262 {
263         struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
264         struct fuse_bank *bank = &ocotp->bank[0];
265         struct fuse_bank0_regs *fuse =
266                 (struct fuse_bank0_regs *)bank->fuse_regs;
267         uint32_t reg = readl(&fuse->cfg5);
268
269         return (reg & 0x2) == 0x2;
270 }
271
272 static inline uint8_t get_idx(uint8_t *list, uint8_t tgt)
273 {
274         uint8_t idx = 0;
275         uint8_t element = list[idx];
276         while (element != -1) {
277                 if (element == tgt)
278                         return idx;
279                 element = list[++idx];
280         }
281         return -1;
282 }
283
284 void process_event_record(uint8_t *event_data, size_t bytes)
285 {
286         struct record *rec = (struct record *)event_data;
287
288         printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]);
289         printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]);
290         printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]);
291         printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]);
292 }
293
294 void display_event(uint8_t *event_data, size_t bytes)
295 {
296         uint32_t i;
297
298         if (!(event_data && bytes > 0))
299                 return;
300
301         for (i = 0; i < bytes; i++) {
302                 if (i == 0)
303                         printf("\t0x%02x", event_data[i]);
304                 else if ((i % 8) == 0)
305                         printf("\n\t0x%02x", event_data[i]);
306                 else
307                         printf(" 0x%02x", event_data[i]);
308         }
309
310         process_event_record(event_data, bytes);
311 }
312
313 int get_hab_status(void)
314 {
315         uint32_t index = 0; /* Loop index */
316         uint8_t event_data[128]; /* Event data buffer */
317         size_t bytes = sizeof(event_data); /* Event size in bytes */
318         enum hab_config config = 0;
319         enum hab_state state = 0;
320         hab_rvt_report_event_t *hab_rvt_report_event;
321         hab_rvt_report_status_t *hab_rvt_report_status;
322
323         hab_rvt_report_event = hab_rvt_report_event_p;
324         hab_rvt_report_status = hab_rvt_report_status_p;
325
326         if (is_hab_enabled())
327                 puts("\nSecure boot enabled\n");
328         else
329                 puts("\nSecure boot disabled\n");
330
331         /* Check HAB status */
332         if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) {
333                 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
334                        config, state);
335
336                 /* Display HAB Error events */
337                 while (hab_rvt_report_event(HAB_FAILURE, index, event_data,
338                                         &bytes) == HAB_SUCCESS) {
339                         puts("\n");
340                         printf("--------- HAB Event %d -----------------\n",
341                                index + 1);
342                         puts("event data:\n");
343                         display_event(event_data, bytes);
344                         puts("\n");
345                         bytes = sizeof(event_data);
346                         index++;
347                 }
348         }
349         /* Display message if no HAB events are found */
350         else {
351                 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
352                        config, state);
353                 puts("No HAB Events Found!\n\n");
354         }
355         return 0;
356 }
357
358 uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size)
359 {
360         uint32_t load_addr = 0;
361         size_t bytes;
362         ptrdiff_t ivt_offset = 0;
363         int result = 0;
364         ulong start;
365         hab_rvt_authenticate_image_t *hab_rvt_authenticate_image;
366         hab_rvt_entry_t *hab_rvt_entry;
367         hab_rvt_exit_t *hab_rvt_exit;
368
369         hab_rvt_authenticate_image = hab_rvt_authenticate_image_p;
370         hab_rvt_entry = hab_rvt_entry_p;
371         hab_rvt_exit = hab_rvt_exit_p;
372
373         if (is_hab_enabled()) {
374                 printf("\nAuthenticate image from DDR location 0x%x...\n",
375                        ddr_start);
376
377                 hab_caam_clock_enable(1);
378
379                 if (hab_rvt_entry() == HAB_SUCCESS) {
380                         /* If not already aligned, Align to ALIGN_SIZE */
381                         ivt_offset = (image_size + ALIGN_SIZE - 1) &
382                                         ~(ALIGN_SIZE - 1);
383
384                         start = ddr_start;
385                         bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
386 #ifdef DEBUG
387                         printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n",
388                                ivt_offset, ddr_start + ivt_offset);
389                         puts("Dumping IVT\n");
390                         print_buffer(ddr_start + ivt_offset,
391                                      (void *)(ddr_start + ivt_offset),
392                                      4, 0x8, 0);
393
394                         puts("Dumping CSF Header\n");
395                         print_buffer(ddr_start + ivt_offset+IVT_SIZE,
396                                      (void *)(ddr_start + ivt_offset+IVT_SIZE),
397                                      4, 0x10, 0);
398
399                         get_hab_status();
400
401                         puts("\nCalling authenticate_image in ROM\n");
402                         printf("\tivt_offset = 0x%x\n", ivt_offset);
403                         printf("\tstart = 0x%08lx\n", start);
404                         printf("\tbytes = 0x%x\n", bytes);
405 #endif
406                         /*
407                          * If the MMU is enabled, we have to notify the ROM
408                          * code, or it won't flush the caches when needed.
409                          * This is done, by setting the "pu_irom_mmu_enabled"
410                          * word to 1. You can find its address by looking in
411                          * the ROM map. This is critical for
412                          * authenticate_image(). If MMU is enabled, without
413                          * setting this bit, authentication will fail and may
414                          * crash.
415                          */
416                         /* Check MMU enabled */
417                         if (get_cr() & CR_M) {
418                                 if (is_cpu_type(MXC_CPU_MX6Q) ||
419                                     is_cpu_type(MXC_CPU_MX6D)) {
420                                         /*
421                                          * This won't work on Rev 1.0.0 of
422                                          * i.MX6Q/D, since their ROM doesn't
423                                          * do cache flushes. don't think any
424                                          * exist, so we ignore them.
425                                          */
426                                         if (!is_mx6dqp())
427                                                 writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
428                                 } else if (is_cpu_type(MXC_CPU_MX6DL) ||
429                                            is_cpu_type(MXC_CPU_MX6SOLO)) {
430                                         writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
431                                 } else if (is_cpu_type(MXC_CPU_MX6SL)) {
432                                         writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
433                                 }
434                         }
435
436                         load_addr = (uint32_t)hab_rvt_authenticate_image(
437                                         HAB_CID_UBOOT,
438                                         ivt_offset, (void **)&start,
439                                         (size_t *)&bytes, NULL);
440                         if (hab_rvt_exit() != HAB_SUCCESS) {
441                                 puts("hab exit function fail\n");
442                                 load_addr = 0;
443                         }
444                 } else {
445                         puts("hab entry function fail\n");
446                 }
447
448                 hab_caam_clock_enable(0);
449
450                 get_hab_status();
451         } else {
452                 puts("hab fuse not enabled\n");
453         }
454
455         if ((!is_hab_enabled()) || (load_addr != 0))
456                 result = 1;
457
458         return result;
459 }
460
461 int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
462 {
463         if ((argc != 1)) {
464                 cmd_usage(cmdtp);
465                 return 1;
466         }
467
468         get_hab_status();
469
470         return 0;
471 }
472
473 static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
474                                 char * const argv[])
475 {
476         ulong   addr, ivt_offset;
477         int     rcode = 0;
478
479         if (argc < 3)
480                 return CMD_RET_USAGE;
481
482         addr = simple_strtoul(argv[1], NULL, 16);
483         ivt_offset = simple_strtoul(argv[2], NULL, 16);
484
485         rcode = authenticate_image(addr, ivt_offset);
486
487         return rcode;
488 }
489
490 U_BOOT_CMD(
491                 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
492                 "display HAB status",
493                 ""
494           );
495
496 U_BOOT_CMD(
497                 hab_auth_img, 3, 0, do_authenticate_image,
498                 "authenticate image via HAB",
499                 "addr ivt_offset\n"
500                 "addr - image hex address\n"
501                 "ivt_offset - hex offset of IVT in the image"
502           );