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