karo: tx6: cleanup HAB functions
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / mx6 / hab.c
1 /*
2  * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:    GPL-2.0+
5  */
6 #include <common.h>
7 #include <asm/io.h>
8 #include <asm/system.h>
9 #include <asm/arch/clock.h>
10 #include <asm/arch/sys_proto.h>
11 #include <asm/arch/hab.h>
12
13 HAB_FUNC(entry, hab_status_t)
14 HAB_FUNC(exit, hab_status_t)
15 HAB_FUNC5(authenticate_image, void *, uint8_t, size_t, void **, size_t *, hab_loader_callback_f_t)
16 //HAB_FUNC1(run_dcd, hab_status_t, const uint8_t *)
17 HAB_FUNC2(run_csf, hab_status_t, const uint8_t *, uint8_t)
18 HAB_FUNC2(report_status, hab_status_t, hab_config_t *, hab_state_t *)
19 HAB_FUNC4(report_event, hab_status_t, hab_status_t, uint32_t, uint8_t *, size_t *)
20 HAB_FUNC3(check_target, hab_status_t, uint8_t, const void *, size_t)
21 HAB_FUNC3(assert, hab_status_t, uint8_t, const void *, size_t)
22
23 struct mx6_ivt {
24         u32 header;
25         u32 entry;
26         u32 rsrvd1;
27         void *dcd;
28         struct mx6_boot_data *boot_data;
29         void *self;
30         void *csf;
31         u32 rsrvd2;
32 };
33
34 struct mx6_boot_data {
35         void *start;
36         u32 length;
37         u32 plugin;
38 };
39
40 #define IVT_SIZE                0x20
41 #define ALIGN_SIZE              0x400
42 #define CSF_PAD_SIZE            0x2000
43 #define MX6DQ_PU_IROM_MMU_EN_VAR        0x009024a8
44 #define MX6DLS_PU_IROM_MMU_EN_VAR       0x00901dd0
45 #define MX6SL_PU_IROM_MMU_EN_VAR        0x00900a18
46
47 /*
48  * +------------+  0x0 (DDR_UIMAGE_START) -
49  * |   Header   |                          |
50  * +------------+  0x40                    |
51  * |            |                          |
52  * |            |                          |
53  * |            |                          |
54  * |            |                          |
55  * | Image Data |                          |
56  * .            |                          |
57  * .            |                           > Stuff to be authenticated ----+
58  * .            |                          |                                |
59  * |            |                          |                                |
60  * |            |                          |                                |
61  * +------------+                          |                                |
62  * |            |                          |                                |
63  * | Fill Data  |                          |                                |
64  * |            |                          |                                |
65  * +------------+ Align to ALIGN_SIZE      |                                |
66  * |    IVT     |                          |                                |
67  * +------------+ + IVT_SIZE              -                                 |
68  * |            |                                                           |
69  * |  CSF DATA  | <---------------------------------------------------------+
70  * |            |
71  * +------------+
72  * |            |
73  * | Fill Data  |
74  * |            |
75  * +------------+ + CSF_PAD_SIZE
76  */
77
78 static bool is_hab_enabled(void)
79 {
80         struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
81         struct fuse_bank *bank = &ocotp->bank[0];
82         struct fuse_bank0_regs *fuse =
83                 (struct fuse_bank0_regs *)bank->fuse_regs;
84         uint32_t reg = readl(&fuse->cfg5);
85         static int first = 1;
86
87         if (first) {
88                 debug("rvt_base=%p\n", hab_rvt_base());
89                 debug("hab_rvt_entry=%p\n", hab_rvt_entry_p);
90                 debug("hab_rvt_exit=%p\n", hab_rvt_exit_p);
91                 debug("hab_rvt_check_target=%p\n", hab_rvt_check_target_p);
92                 debug("hab_rvt_authenticate_image=%p\n", hab_rvt_authenticate_image_p);
93                 debug("hab_rvt_report_event=%p\n", hab_rvt_report_event_p);
94                 debug("hab_rvt_report_status=%p\n", hab_rvt_report_status_p);
95                 debug("hab_rvt_assert=%p\n", hab_rvt_assert_p);
96                 first = 0;
97         }
98         return (reg & 0x2) == 0x2;
99 }
100
101 static void display_event(uint8_t *event_data, size_t bytes)
102 {
103         uint32_t i;
104
105         if (!(event_data && bytes > 0))
106                 return;
107
108         for (i = 0; i < bytes; i++) {
109                 if (i == 0)
110                         printf("\t0x%02x", event_data[i]);
111                 else if ((i % 8) == 0)
112                         printf("\n\t0x%02x", event_data[i]);
113                 else
114                         printf(" 0x%02x", event_data[i]);
115         }
116 }
117
118 int get_hab_status(void)
119 {
120         static uint32_t last_hab_event __attribute__((section(".data")));
121         uint32_t index = last_hab_event; /* Loop index */
122         uint8_t event_data[128]; /* Event data buffer */
123         size_t bytes = sizeof(event_data); /* Event size in bytes */
124         enum hab_config config;
125         enum hab_state state;
126         int ret;
127
128         if (is_hab_enabled())
129                 puts("Secure boot enabled\n");
130         else
131                 puts("Secure boot disabled\n");
132
133         /* Check HAB status */
134         config = state = 0; /* ROM code assumes short enums! */
135         ret = hab_rvt_report_status(&config, &state);
136         printf("HAB Configuration: 0x%02x, HAB State: 0x%02x\n",
137                 config, state);
138         if (ret != HAB_SUCCESS) {
139                 /* Display HAB Error events */
140                 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
141                                         &bytes) == HAB_SUCCESS) {
142                         puts("\n");
143                         printf("--------- HAB Event %d -----------------\n",
144                                index + 1);
145                         puts("event data:\n");
146                         display_event(event_data, bytes);
147                         puts("\n");
148                         bytes = sizeof(event_data);
149                         index++;
150                 }
151                 ret = index - last_hab_event;
152                 last_hab_event = index;
153         } else {
154                 /* Display message if no HAB events are found */
155                 puts("No HAB Events Found!\n");
156                 ret = 0;
157         }
158         return ret;
159 }
160
161 static inline hab_status_t hab_init(void)
162 {
163         hab_status_t ret;
164
165         if (!is_hab_enabled()) {
166                 puts("hab fuse not enabled\n");
167                 return HAB_FAILURE;
168         }
169
170         hab_caam_clock_enable(1);
171
172         ret = hab_rvt_entry();
173         debug("hab_rvt_entry() returned %02x\n", ret);
174         if (ret != HAB_SUCCESS) {
175                 printf("hab entry function failed: %02x\n", ret);
176                 hab_caam_clock_enable(0);
177         }
178
179         return ret;
180 }
181
182 static inline hab_status_t hab_exit(void)
183 {
184         hab_status_t ret;
185
186         ret = hab_rvt_exit();
187         if (ret != HAB_SUCCESS)
188                 printf("hab exit function failed: %02x\n", ret);
189
190         hab_caam_clock_enable(0);
191
192         return ret;
193 }
194
195 static hab_status_t hab_check_target(hab_target_t type, uint32_t addr, size_t len)
196 {
197         hab_status_t ret;
198
199         ret = hab_init();
200         if (ret != HAB_SUCCESS)
201                 return ret;
202
203         ret = hab_rvt_check_target(type, (void *)addr, len);
204         if (ret != HAB_SUCCESS) {
205                 printf("check_target(0x%08x, 0x%08x) failed: %d\n",
206                         addr, len, ret);
207                 return ret;
208         }
209         ret = hab_exit();
210
211         if (ret == HAB_SUCCESS && get_hab_status() > 0) {
212                 return HAB_FAILURE;
213         }
214         return ret;
215 }
216
217 static hab_status_t hab_assert(uint32_t type, uint32_t addr, size_t len)
218 {
219         hab_status_t ret;
220
221         ret = hab_init();
222         if (ret != HAB_SUCCESS)
223                 return ret;
224
225         ret = hab_rvt_assert(type, (void *)addr, len);
226         if (ret != HAB_SUCCESS) {
227                 printf("assert(0x%08x, 0x%08x) failed: %d\n",
228                         addr, len, ret);
229                 return ret;
230         }
231         ret = hab_exit();
232
233         if (ret == HAB_SUCCESS && get_hab_status() > 0) {
234                 return HAB_FAILURE;
235         }
236         return ret;
237 }
238
239 static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc,
240                         char *const argv[])
241 {
242         if (argc != 1)
243                 return CMD_RET_USAGE;
244
245         get_hab_status();
246
247         return CMD_RET_SUCCESS;
248 }
249
250 static int do_hab_check_target(cmd_tbl_t *cmdtp, int flag, int argc,
251                         char *const argv[])
252 {
253         hab_target_t type = HAB_TGT_ANY;
254         uint32_t addr;
255         size_t len;
256
257         if (argc < 3)
258                 return CMD_RET_USAGE;
259
260         addr = simple_strtoul(argv[1], NULL, 16);
261         len = simple_strtoul(argv[2], NULL, 16);
262         if (argc > 3) {
263                 switch (argv[3][0]) {
264                 case 'p':
265                 case 'P':
266                         type = HAB_TGT_PERIPHERAL;
267                         break;
268                 case 'm':
269                 case 'M':
270                         type = HAB_TGT_MEMORY;
271                         break;
272                 case 'a':
273                 case 'A':
274                         break;
275                 default:
276                         printf("Invalid type '%s'\n", argv[3]);
277                         return CMD_RET_USAGE;
278                 }
279         }
280         if (hab_check_target(type, addr, len) != HAB_SUCCESS)
281                 return CMD_RET_FAILURE;
282
283         return CMD_RET_SUCCESS;
284 }
285
286 static int do_hab_assert(cmd_tbl_t *cmdtp, int flag, int argc,
287                         char *const argv[])
288 {
289         uint32_t type = 0;
290         uint32_t addr;
291         size_t len;
292
293         if (argc < 3)
294                 return CMD_RET_USAGE;
295
296         addr = simple_strtoul(argv[1], NULL, 16);
297         len = simple_strtoul(argv[2], NULL, 16);
298         if (argc > 3) {
299                 type = simple_strtoul(argv[3], NULL, 16);
300         }
301
302         if (hab_assert(type, addr, len) != HAB_SUCCESS)
303                 return CMD_RET_FAILURE;
304
305         return CMD_RET_SUCCESS;
306 }
307
308 U_BOOT_CMD(
309                 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
310                 "display HAB status",
311                 ""
312           );
313
314 U_BOOT_CMD(
315                 hab_check_target, 4, 0, do_hab_check_target,
316                 "verify an address range via HAB",
317                 "addr len [type]\n"
318                 "\t\taddr -\taddress to verify\n"
319                 "\t\tlen -\tlength of addr range to verify\n"
320           );
321
322 U_BOOT_CMD(
323                 hab_assert, 4, 0, do_hab_assert,
324                 "Test an assertion against the HAB audit log",
325                 "addr len [type]\n"
326                 "\t\taddr -\taddress to verify\n"
327                 "\t\tlen -\tlength of addr range to verify\n"
328           );