1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2018-2021 NXP
4 */
5
6 #define LOG_CATEGORY LOGC_ARCH
7 #include <stdlib.h>
8 #include <errno.h>
9 #include <imx_container.h>
10 #include <log.h>
11 #include <mapmem.h>
12 #include <spl.h>
13 #ifdef CONFIG_AHAB_BOOT
14 #include <asm/mach-imx/ahab.h>
15 #endif
16
arch_check_dst_in_secure(void * start,ulong size)17 __weak bool arch_check_dst_in_secure(void *start, ulong size)
18 {
19 return false;
20 }
21
arch_get_container_trampoline(void)22 __weak void *arch_get_container_trampoline(void)
23 {
24 return NULL;
25 }
26
read_auth_image(struct spl_image_info * spl_image,struct spl_load_info * info,struct container_hdr * container,int image_index,ulong container_offset)27 static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image,
28 struct spl_load_info *info,
29 struct container_hdr *container,
30 int image_index,
31 ulong container_offset)
32 {
33 struct boot_img_t *images;
34 ulong offset, size;
35 void *buf, *trampoline;
36
37 if (image_index > container->num_images) {
38 debug("Invalid image number\n");
39 return NULL;
40 }
41
42 images = (struct boot_img_t *)((u8 *)container +
43 sizeof(struct container_hdr));
44
45 if (!IS_ALIGNED(images[image_index].offset, spl_get_bl_len(info))) {
46 printf("%s: image%d offset not aligned to %u\n",
47 __func__, image_index, spl_get_bl_len(info));
48 return NULL;
49 }
50
51 size = ALIGN(images[image_index].size, spl_get_bl_len(info));
52 offset = images[image_index].offset + container_offset;
53
54 debug("%s: container: %p offset: %lu size: %lu\n", __func__,
55 container, offset, size);
56
57 buf = map_sysmem(images[image_index].dst, images[image_index].size);
58 if (IS_ENABLED(CONFIG_SPL_IMX_CONTAINER_USE_TRAMPOLINE) &&
59 arch_check_dst_in_secure(buf, size)) {
60 trampoline = arch_get_container_trampoline();
61 if (!trampoline) {
62 printf("%s: trampoline size is zero\n", __func__);
63 return NULL;
64 }
65
66 if (info->read(info, offset, size, trampoline) < images[image_index].size) {
67 printf("%s: failed to load image to a trampoline buffer\n", __func__);
68 return NULL;
69 }
70
71 memcpy(buf, trampoline, images[image_index].size);
72 } else {
73 if (info->read(info, offset, size, buf) < images[image_index].size) {
74 printf("%s: failed to load image to a non-secure region\n", __func__);
75 return NULL;
76 }
77 }
78
79 #ifdef CONFIG_AHAB_BOOT
80 if (ahab_verify_cntr_image(&images[image_index], image_index))
81 return NULL;
82 #endif
83
84 return &images[image_index];
85 }
86
read_auth_container(struct spl_image_info * spl_image,struct spl_load_info * info,ulong offset)87 static int read_auth_container(struct spl_image_info *spl_image,
88 struct spl_load_info *info, ulong offset)
89 {
90 struct container_hdr *container = NULL;
91 u16 length;
92 int i, size, ret = 0;
93
94 size = ALIGN(CONTAINER_HDR_ALIGNMENT, spl_get_bl_len(info));
95
96 /*
97 * It will not override the ATF code, so safe to use it here,
98 * no need malloc
99 */
100 container = malloc(size);
101 if (!container)
102 return -ENOMEM;
103
104 debug("%s: container: %p offset: %lu size: %u\n", __func__,
105 container, offset, size);
106 if (info->read(info, offset, size, container) <
107 CONTAINER_HDR_ALIGNMENT) {
108 ret = -EIO;
109 goto end;
110 }
111
112 if (!valid_container_hdr(container)) {
113 log_err("Wrong container header\n");
114 ret = -ENOENT;
115 goto end;
116 }
117
118 if (!container->num_images) {
119 log_err("Wrong container, no image found\n");
120 ret = -ENOENT;
121 goto end;
122 }
123
124 length = container->length_lsb + (container->length_msb << 8);
125 debug("Container length %u\n", length);
126
127 if (length > CONTAINER_HDR_ALIGNMENT) {
128 size = ALIGN(length, spl_get_bl_len(info));
129
130 free(container);
131 container = malloc(size);
132 if (!container)
133 return -ENOMEM;
134
135 debug("%s: container: %p offset: %lu size: %u\n",
136 __func__, container, offset, size);
137 if (info->read(info, offset, size, container) < length) {
138 ret = -EIO;
139 goto end;
140 }
141 }
142
143 #ifdef CONFIG_AHAB_BOOT
144 ret = ahab_auth_cntr_hdr(container, length);
145 if (ret)
146 goto end_auth;
147 #endif
148
149 for (i = 0; i < container->num_images; i++) {
150 struct boot_img_t *image = read_auth_image(spl_image, info,
151 container, i,
152 offset);
153
154 if (!image) {
155 ret = -EINVAL;
156 goto end_auth;
157 }
158
159 if (i == 0) {
160 spl_image->load_addr = image->dst;
161 spl_image->entry_point = image->entry;
162 }
163 }
164
165 end_auth:
166 #ifdef CONFIG_AHAB_BOOT
167 ahab_auth_release();
168 #endif
169
170 end:
171 free(container);
172
173 return ret;
174 }
175
spl_load_imx_container(struct spl_image_info * spl_image,struct spl_load_info * info,ulong offset)176 int spl_load_imx_container(struct spl_image_info *spl_image,
177 struct spl_load_info *info, ulong offset)
178 {
179 return read_auth_container(spl_image, info, offset);
180 }
181