xref: /OK3568_Linux_fs/u-boot/common/spl/spl_boot_image.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * (C) Copyright 2023 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <android_image.h>
9 #include <crypto.h>
10 #include <image.h>
11 #include <mp_boot.h>
12 #include <part.h>
13 #include <spl.h>
14 #include <asm/io.h>
15 
16 #define BLK_CNT(_num_bytes, _block_size) \
17 		((_num_bytes + _block_size - 1) / _block_size)
18 
19 #ifdef CONFIG_ANDROID_BOOT_IMAGE
android_check_header(const struct andr_img_hdr * hdr)20 static int android_check_header(const struct andr_img_hdr *hdr)
21 {
22 	return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE);
23 }
24 
print_hash(const char * label,u8 * hash,int len)25 static void print_hash(const char *label, u8 *hash, int len)
26 {
27 	int i;
28 
29 	printf("%s:\n    0x", label ? : "Hash");
30 	for (i = 0; i < len; i++)
31 		printf("%02x", hash[i]);
32 	printf("\n");
33 }
34 
35 #if 0
36 static void spl_android_print_contents(const struct andr_img_hdr *hdr)
37 {
38 	const char * const p = IMAGE_INDENT_STRING;
39 	/* os_version = ver << 11 | lvl */
40 	u32 os_ver = hdr->os_version >> 11;
41 	u32 os_lvl = hdr->os_version & ((1U << 11) - 1);
42 	u32 header_version = hdr->header_version;
43 
44 	printf("%skernel size:      %x\n", p, hdr->kernel_size);
45 	printf("%skernel address:   %x\n", p, hdr->kernel_addr);
46 	printf("%sramdisk size:     %x\n", p, hdr->ramdisk_size);
47 	printf("%sramdisk address: %x\n", p, hdr->ramdisk_addr);
48 	printf("%ssecond size:      %x\n", p, hdr->second_size);
49 	printf("%ssecond address:   %x\n", p, hdr->second_addr);
50 	printf("%stags address:     %x\n", p, hdr->tags_addr);
51 	printf("%spage size:        %x\n", p, hdr->page_size);
52 	printf("%sheader_version:   %x\n", p, header_version);
53 	/* ver = A << 14 | B << 7 | C         (7 bits for each of A, B, C)
54 	 * lvl = ((Y - 2000) & 127) << 4 | M  (7 bits for Y, 4 bits for M) */
55 	printf("%sos_version:       %x (ver: %u.%u.%u, level: %u.%u)\n",
56 	       p, hdr->os_version,
57 	       (os_ver >> 7) & 0x7F, (os_ver >> 14) & 0x7F, os_ver & 0x7F,
58 	       (os_lvl >> 4) + 2000, os_lvl & 0x0F);
59 	printf("%sname:             %s\n", p, hdr->name);
60 	printf("%scmdline:          %s\n", p, hdr->cmdline);
61 
62 	if (header_version == 1 || header_version == 2) {
63 		printf("%srecovery dtbo size:    %x\n", p, hdr->recovery_dtbo_size);
64 		printf("%srecovery dtbo offset:  %llx\n", p, hdr->recovery_dtbo_offset);
65 		printf("%sheader size:           %x\n", p, hdr->header_size);
66 	}
67 
68 	if (header_version == 2 || header_version == 3) {
69 		printf("%sdtb size:              %x\n", p, hdr->dtb_size);
70 		printf("%sdtb addr:              %llx\n", p, hdr->dtb_addr);
71 	}
72 
73 	if (header_version >= 3) {
74 		printf("%scmdline:               %s\n", p, hdr->total_cmdline);
75 		printf("%svendor ramdisk size:   %x\n", p, hdr->vendor_ramdisk_size);
76 		printf("%svendor page size:      %x\n", p, hdr->vendor_page_size);
77 		printf("%svendor header version: %d\n", p, hdr->vendor_header_version);
78 		printf("%svendor header size:    %x\n", p, hdr->vendor_header_size);
79 	}
80 
81 	if (header_version >= 4) {
82 		printf("%svendor ramdisk table size:        %x\n",
83 		       p, hdr->vendor_ramdisk_table_size);
84 		printf("%svendor ramdisk table entry num:   %x\n",
85 		       p, hdr->vendor_ramdisk_table_entry_num);
86 		printf("%svendor ramdisk table entry size:  %x\n",
87 		       p, hdr->vendor_ramdisk_table_entry_size);
88 		printf("%svendor bootconfig size:           %d\n",
89 		       p, hdr->vendor_bootconfig_size);
90 	}
91 }
92 #endif
93 
android_size(struct andr_img_hdr * hdr)94 static ulong android_size(struct andr_img_hdr *hdr)
95 {
96 	ulong len;
97 
98 	len = hdr->page_size +
99 		ALIGN(hdr->kernel_size, hdr->page_size) +
100 		ALIGN(hdr->ramdisk_size, hdr->page_size) +
101 		ALIGN(hdr->second_size, hdr->page_size);
102 	if (hdr->header_version > 0)
103 		len += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
104 	if (hdr->header_version > 1)
105 		len += ALIGN(hdr->dtb_size, hdr->page_size);
106 #if 0
107 	spl_android_print_contents(hdr);
108 #endif
109 
110 	return len;
111 }
112 
spl_load_android(struct task_data * data)113 int spl_load_android(struct task_data *data)
114 {
115 	struct spl_load_info *info = &data->info;
116 	void *buf = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
117 	disk_partition_t part;
118 	ulong blkcnt;
119 
120 	debug("== Android: load start\n");
121 
122 	if (part_get_info_by_name(info->dev, "boot", &part) < 0) {
123 		printf("No boot partition\n");
124 		return -ENOENT;
125 	}
126 
127 	blkcnt = BLK_CNT(sizeof(struct andr_img_hdr), info->bl_len);
128 	if (info->read(info, part.start, blkcnt, buf) != blkcnt)
129 		return -EIO;
130 
131 	if (android_check_header(buf))
132 		return -EINVAL;
133 
134 	blkcnt = BLK_CNT(android_size(buf), info->bl_len);
135 	if (info->read(info, part.start, blkcnt, buf) != blkcnt)
136 		return -EIO;
137 
138 	data->boot_addr = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
139 	data->boot_size = blkcnt * info->bl_len;
140 
141 	flush_dcache_range((ulong)data, (ulong)data + sizeof(*data));
142 	flush_dcache_range((ulong)buf, (ulong)buf + blkcnt);
143 
144 	debug("== Android: load 0x%08lx size OK\n", blkcnt * info->bl_len);
145 
146 	return 0;
147 }
148 
149 #ifdef CONFIG_ARMV8_CE_SHA1
spl_hash_android(struct task_data * data)150 int spl_hash_android(struct task_data *data)
151 {
152 	struct andr_img_hdr *hdr = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
153 	sha1_context ctx;
154 	uchar hash[32];
155 	void *buf;
156 
157 	printf("== Android: hash start\n");
158 
159 	if (hdr->header_version >= 3)
160 		return -EINVAL;
161 
162 	sha1_starts(&ctx);
163 
164 	buf = (void *)hdr + hdr->page_size;
165 	sha1_update(&ctx, (const uchar *)buf, hdr->kernel_size);
166 	sha1_update(&ctx, (const uchar *)&hdr->kernel_size, sizeof(hdr->kernel_size));
167 
168 	buf += ALIGN(hdr->kernel_size, hdr->page_size);
169 	sha1_update(&ctx, (const uchar *)buf, hdr->ramdisk_size);
170 	sha1_update(&ctx, (const uchar *)&hdr->ramdisk_size, sizeof(hdr->ramdisk_size));
171 
172 	buf += ALIGN(hdr->ramdisk_size, hdr->page_size);
173 	sha1_update(&ctx, (const uchar *)buf, hdr->second_size);
174 	sha1_update(&ctx, (const uchar *)&hdr->second_size, sizeof(hdr->second_size));
175 
176 	if (hdr->header_version > 0) {
177 		buf += ALIGN(hdr->second_size, hdr->page_size);
178 		sha1_update(&ctx, (const uchar *)buf, hdr->recovery_dtbo_size);
179 		sha1_update(&ctx, (const uchar *)&hdr->recovery_dtbo_size, sizeof(hdr->recovery_dtbo_size));
180 	}
181 	if (hdr->header_version > 1) {
182 		buf += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
183 		sha1_update(&ctx, (const uchar *)buf, hdr->dtb_size);
184 		sha1_update(&ctx, (const uchar *)&hdr->dtb_size, sizeof(hdr->dtb_size));
185 	}
186 
187 	sha1_finish(&ctx, hash);
188 
189 	if (memcmp(hash, hdr->id, 20)) {
190 		print_hash("Hash from header", (u8 *)hdr->id, 20);
191 		print_hash("Hash real", (u8 *)hash, 20);
192 		return -EBADFD;
193 	}
194 
195 	printf("== Android: hash OK, 0x%08lx\n", (ulong)data->boot_addr);
196 
197 	return 0;
198 }
199 
200 #else
spl_hash_android(struct task_data * data)201 int spl_hash_android(struct task_data *data)
202 {
203 	struct andr_img_hdr *hdr = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
204 	struct udevice *dev;
205 	sha_context ctx;
206 	uchar hash[32];
207 	void *buf;
208 
209 	debug("== Android: hash start\n");
210 
211 	if (hdr->header_version >= 3)
212 		return -EINVAL;
213 
214 	ctx.algo = CRYPTO_SHA1;
215 	dev = crypto_get_device(ctx.algo);
216 	if (!dev) {
217 		printf("No crypto device for sha1\n");
218 		return -ENODEV;
219 	}
220 
221 	ctx.length = hdr->kernel_size + sizeof(hdr->kernel_size) +
222 	      hdr->ramdisk_size + sizeof(hdr->ramdisk_size) +
223 	      hdr->second_size + sizeof(hdr->second_size);
224 	if (hdr->header_version > 0)
225 		ctx.length += hdr->recovery_dtbo_size + sizeof(hdr->recovery_dtbo_size);
226 	if (hdr->header_version > 1)
227 		ctx.length += hdr->dtb_size + sizeof(hdr->dtb_size);
228 
229 	crypto_sha_init(dev, &ctx);
230 
231 	buf = (void *)hdr + hdr->page_size;
232 	crypto_sha_update(dev, buf, hdr->kernel_size);
233 	crypto_sha_update(dev, &hdr->kernel_size, sizeof(hdr->kernel_size));
234 
235 	buf += ALIGN(hdr->kernel_size, hdr->page_size);
236 	crypto_sha_update(dev, buf, hdr->ramdisk_size);
237 	crypto_sha_update(dev, &hdr->ramdisk_size, sizeof(hdr->ramdisk_size));
238 
239 	buf += ALIGN(hdr->ramdisk_size, hdr->page_size);
240 	crypto_sha_update(dev, buf, hdr->second_size);
241 	crypto_sha_update(dev, &hdr->second_size, sizeof(hdr->second_size));
242 
243 	if (hdr->header_version > 0) {
244 		buf += ALIGN(hdr->second_size, hdr->page_size);
245 		crypto_sha_update(dev, buf, hdr->recovery_dtbo_size);
246 		crypto_sha_update(dev, &hdr->recovery_dtbo_size, sizeof(hdr->recovery_dtbo_size));
247 	}
248 	if (hdr->header_version > 1) {
249 		buf += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
250 		crypto_sha_update(dev, buf, hdr->dtb_size);
251 		crypto_sha_update(dev, &hdr->dtb_size, sizeof(hdr->dtb_size));
252 	}
253 
254 	crypto_sha_final(dev, &ctx, hash);
255 
256 	if (memcmp(hash, hdr->id, 20)) {
257 		print_hash("Hash from header", (u8 *)hdr->id, 20);
258 		print_hash("Hash real", (u8 *)hash, 20);
259 		return -EBADFD;
260 	}
261 
262 	debug("== Android: hash OK, 0x%08lx\n", (ulong)data->boot_addr);
263 
264 	return 0;
265 }
266 
267 #endif
268 #endif
269 
270 #ifdef CONFIG_ROCKCHIP_FIT_IMAGE
spl_load_fit(struct task_data * data)271 int spl_load_fit(struct task_data *data)
272 {
273 	struct spl_load_info *info = &data->info;
274 	void *buf = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
275 	disk_partition_t part;
276 	ulong blkcnt;
277 	int size;
278 
279 	debug("== FIT: load start\n");
280 
281 	if (part_get_info_by_name(info->dev, "boot", &part) < 0) {
282 	        printf("No boot partition\n");
283 		return -ENOENT;
284 	}
285 
286 	blkcnt = BLK_CNT(sizeof(struct fdt_header), info->bl_len);
287 	if (info->read(info, part.start, blkcnt, buf) != blkcnt)
288 		return -EIO;
289 
290 	if (fdt_check_header(buf))
291 		return -EINVAL;
292 
293 	size = fit_get_totalsize(buf, &size);
294 	blkcnt = BLK_CNT(size, info->bl_len);
295 	if (info->read(info, part.start, blkcnt, buf) != blkcnt)
296 		return -EIO;
297 
298 	flush_dcache_range((ulong)buf, (ulong)buf + blkcnt);
299 
300 	debug("== FIT: load 0x%08x size OK\n", size);
301 
302 	return 0;
303 }
304 #endif
305 
306