imx8: Change to use new SECO API commands
[oweals/u-boot.git] / arch / arm / mach-imx / imx8 / parse-container.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2018-2019 NXP
4  */
5
6 #include <common.h>
7 #include <errno.h>
8 #include <spl.h>
9 #include <asm/arch/image.h>
10 #include <asm/arch/sci/sci.h>
11
12 #define SEC_SECURE_RAM_BASE             0x31800000UL
13 #define SEC_SECURE_RAM_END_BASE         (SEC_SECURE_RAM_BASE + 0xFFFFUL)
14 #define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE      0x60000000UL
15
16 #define SECO_PT         2U
17
18 #ifdef CONFIG_AHAB_BOOT
19 static int authenticate_image(struct boot_img_t *img, int image_index)
20 {
21         sc_faddr_t start, end;
22         sc_rm_mr_t mr;
23         int err;
24         int ret = 0;
25
26         debug("img %d, dst 0x%llx, src 0x%x, size 0x%x\n",
27               image_index, img->dst, img->offset, img->size);
28
29         /* Find the memreg and set permission for seco pt */
30         err = sc_rm_find_memreg(-1, &mr,
31                                 img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1),
32                                 ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE) - 1);
33
34         if (err) {
35                 printf("can't find memreg for image: %d, err %d\n",
36                        image_index, err);
37                 return -ENOMEM;
38         }
39
40         err = sc_rm_get_memreg_info(-1, mr, &start, &end);
41         if (!err)
42                 debug("memreg %u 0x%llx -- 0x%llx\n", mr, start, end);
43
44         err = sc_rm_set_memreg_permissions(-1, mr,
45                                            SECO_PT, SC_RM_PERM_FULL);
46         if (err) {
47                 printf("set permission failed for img %d, error %d\n",
48                        image_index, err);
49                 return -EPERM;
50         }
51
52         err = sc_seco_authenticate(-1, SC_SECO_VERIFY_IMAGE,
53                                    1 << image_index);
54         if (err) {
55                 printf("authenticate img %d failed, return %d\n",
56                        image_index, err);
57                 ret = -EIO;
58         }
59
60         err = sc_rm_set_memreg_permissions(-1, mr,
61                                            SECO_PT, SC_RM_PERM_NONE);
62         if (err) {
63                 printf("remove permission failed for img %d, error %d\n",
64                        image_index, err);
65                 ret = -EPERM;
66         }
67
68         return ret;
69 }
70 #endif
71
72 static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image,
73                                           struct spl_load_info *info,
74                                           struct container_hdr *container,
75                                           int image_index,
76                                           u32 container_sector)
77 {
78         struct boot_img_t *images;
79         ulong sector;
80         u32 sectors;
81
82         if (image_index > container->num_images) {
83                 debug("Invalid image number\n");
84                 return NULL;
85         }
86
87         images = (struct boot_img_t *)((u8 *)container +
88                                        sizeof(struct container_hdr));
89
90         if (images[image_index].offset % info->bl_len) {
91                 printf("%s: image%d offset not aligned to %u\n",
92                        __func__, image_index, info->bl_len);
93                 return NULL;
94         }
95
96         sectors = roundup(images[image_index].size, info->bl_len) /
97                 info->bl_len;
98         sector = images[image_index].offset / info->bl_len +
99                 container_sector;
100
101         debug("%s: container: %p sector: %lu sectors: %u\n", __func__,
102               container, sector, sectors);
103         if (info->read(info, sector, sectors,
104                        (void *)images[image_index].entry) != sectors) {
105                 printf("%s wrong\n", __func__);
106                 return NULL;
107         }
108
109 #ifdef CONFIG_AHAB_BOOT
110         if (authenticate_image(&images[image_index], image_index)) {
111                 printf("Failed to authenticate image %d\n", image_index);
112                 return NULL;
113         }
114 #endif
115
116         return &images[image_index];
117 }
118
119 static int read_auth_container(struct spl_image_info *spl_image,
120                                struct spl_load_info *info, ulong sector)
121 {
122         struct container_hdr *container = NULL;
123         u16 length;
124         u32 sectors;
125         int i, size, ret = 0;
126
127         size = roundup(CONTAINER_HDR_ALIGNMENT, info->bl_len);
128         sectors = size / info->bl_len;
129
130         /*
131          * It will not override the ATF code, so safe to use it here,
132          * no need malloc
133          */
134         container = (struct container_hdr *)spl_get_load_buffer(-size, size);
135
136         debug("%s: container: %p sector: %lu sectors: %u\n", __func__,
137               container, sector, sectors);
138         if (info->read(info, sector, sectors, container) != sectors)
139                 return -EIO;
140
141         if (container->tag != 0x87 && container->version != 0x0) {
142                 printf("Wrong container header");
143                 return -ENOENT;
144         }
145
146         if (!container->num_images) {
147                 printf("Wrong container, no image found");
148                 return -ENOENT;
149         }
150
151         length = container->length_lsb + (container->length_msb << 8);
152         debug("Container length %u\n", length);
153
154         if (length > CONTAINER_HDR_ALIGNMENT) {
155                 size = roundup(length, info->bl_len);
156                 sectors = size / info->bl_len;
157
158                 container = (struct container_hdr *)spl_get_load_buffer(-size, size);
159
160                 debug("%s: container: %p sector: %lu sectors: %u\n",
161                       __func__, container, sector, sectors);
162                 if (info->read(info, sector, sectors, container) !=
163                     sectors)
164                         return -EIO;
165         }
166
167 #ifdef CONFIG_AHAB_BOOT
168         memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)container,
169                ALIGN(length, CONFIG_SYS_CACHELINE_SIZE));
170
171         ret = sc_seco_authenticate(-1, SC_SECO_AUTH_CONTAINER,
172                                    SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE);
173         if (ret) {
174                 printf("authenticate container hdr failed, return %d\n", ret);
175                 return ret;
176         }
177 #endif
178
179         for (i = 0; i < container->num_images; i++) {
180                 struct boot_img_t *image = read_auth_image(spl_image, info,
181                                                            container, i,
182                                                            sector);
183
184                 if (!image) {
185                         ret = -EINVAL;
186                         goto end_auth;
187                 }
188
189                 if (i == 0) {
190                         spl_image->load_addr = image->dst;
191                         spl_image->entry_point = image->entry;
192                 }
193         }
194
195 end_auth:
196 #ifdef CONFIG_AHAB_BOOT
197         if (sc_seco_authenticate(-1, SC_SECO_REL_CONTAINER, 0))
198                 printf("Error: release container failed!\n");
199 #endif
200         return ret;
201 }
202
203 int spl_load_imx_container(struct spl_image_info *spl_image,
204                            struct spl_load_info *info, ulong sector)
205 {
206         return read_auth_container(spl_image, info, sector);
207 }