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