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