]> Git Repo - J-u-boot.git/blob - boot/bootmeth_android.c
Merge tag 'u-boot-imx-master-20250127' of https://gitlab.denx.de/u-boot/custodians...
[J-u-boot.git] / boot / bootmeth_android.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Bootmeth for Android
4  *
5  * Copyright (C) 2024 BayLibre, SAS
6  * Written by Mattijs Korpershoek <[email protected]>
7  */
8 #define LOG_CATEGORY UCLASS_BOOTSTD
9
10 #include <android_ab.h>
11 #include <android_image.h>
12 #if CONFIG_IS_ENABLED(AVB_VERIFY)
13 #include <avb_verify.h>
14 #endif
15 #include <bcb.h>
16 #include <blk.h>
17 #include <bootflow.h>
18 #include <bootm.h>
19 #include <bootmeth.h>
20 #include <dm.h>
21 #include <image.h>
22 #include <malloc.h>
23 #include <mapmem.h>
24 #include <part.h>
25 #include <version.h>
26 #include "bootmeth_android.h"
27
28 #define BCB_FIELD_COMMAND_SZ 32
29 #define BCB_PART_NAME "misc"
30 #define BOOT_PART_NAME "boot"
31 #define VENDOR_BOOT_PART_NAME "vendor_boot"
32 #define SLOT_LEN 2
33
34 /**
35  * struct android_priv - Private data
36  *
37  * This is read from the disk and recorded for use when the full Android
38  * kernel must be loaded and booted
39  *
40  * @boot_mode: Requested boot mode (normal, recovery, bootloader)
41  * @slot: Nul-terminated partition slot suffix read from BCB ("a\0" or "b\0")
42  * @header_version: Android boot image header version
43  */
44 struct android_priv {
45         enum android_boot_mode boot_mode;
46         char *slot;
47         u32 header_version;
48         u32 boot_img_size;
49         u32 vendor_boot_img_size;
50 };
51
52 static int android_check(struct udevice *dev, struct bootflow_iter *iter)
53 {
54         /* This only works on mmc devices */
55         if (bootflow_iter_check_mmc(iter))
56                 return log_msg_ret("mmc", -ENOTSUPP);
57
58         /*
59          * This only works on whole devices, as multiple
60          * partitions are needed to boot Android
61          */
62         if (iter->part != 0)
63                 return log_msg_ret("mmc part", -ENOTSUPP);
64
65         return 0;
66 }
67
68 static int scan_boot_part(struct udevice *blk, struct android_priv *priv)
69 {
70         struct blk_desc *desc = dev_get_uclass_plat(blk);
71         struct disk_partition partition;
72         char partname[PART_NAME_LEN];
73         ulong num_blks, bufsz;
74         char *buf;
75         int ret;
76
77         if (priv->slot)
78                 sprintf(partname, BOOT_PART_NAME "_%s", priv->slot);
79         else
80                 sprintf(partname, BOOT_PART_NAME);
81
82         ret = part_get_info_by_name(desc, partname, &partition);
83         if (ret < 0)
84                 return log_msg_ret("part info", ret);
85
86         num_blks = DIV_ROUND_UP(sizeof(struct andr_boot_img_hdr_v0), desc->blksz);
87         bufsz = num_blks * desc->blksz;
88         buf = malloc(bufsz);
89         if (!buf)
90                 return log_msg_ret("buf", -ENOMEM);
91
92         ret = blk_read(blk, partition.start, num_blks, buf);
93         if (ret != num_blks) {
94                 free(buf);
95                 return log_msg_ret("part read", -EIO);
96         }
97
98         if (!is_android_boot_image_header(buf)) {
99                 free(buf);
100                 return log_msg_ret("header", -ENOENT);
101         }
102
103         if (!android_image_get_bootimg_size(buf, &priv->boot_img_size)) {
104                 free(buf);
105                 return log_msg_ret("get bootimg size", -EINVAL);
106         }
107
108         priv->header_version = ((struct andr_boot_img_hdr_v0 *)buf)->header_version;
109
110         free(buf);
111
112         return 0;
113 }
114
115 static int scan_vendor_boot_part(struct udevice *blk, struct android_priv *priv)
116 {
117         struct blk_desc *desc = dev_get_uclass_plat(blk);
118         struct disk_partition partition;
119         char partname[PART_NAME_LEN];
120         ulong num_blks, bufsz;
121         char *buf;
122         int ret;
123
124         if (priv->slot)
125                 sprintf(partname, VENDOR_BOOT_PART_NAME "_%s", priv->slot);
126         else
127                 sprintf(partname, VENDOR_BOOT_PART_NAME);
128
129         ret = part_get_info_by_name(desc, partname, &partition);
130         if (ret < 0)
131                 return log_msg_ret("part info", ret);
132
133         num_blks = DIV_ROUND_UP(sizeof(struct andr_vnd_boot_img_hdr), desc->blksz);
134         bufsz = num_blks * desc->blksz;
135         buf = malloc(bufsz);
136         if (!buf)
137                 return log_msg_ret("buf", -ENOMEM);
138
139         ret = blk_read(blk, partition.start, num_blks, buf);
140         if (ret != num_blks) {
141                 free(buf);
142                 return log_msg_ret("part read", -EIO);
143         }
144
145         if (!is_android_vendor_boot_image_header(buf)) {
146                 free(buf);
147                 return log_msg_ret("header", -ENOENT);
148         }
149
150         if (!android_image_get_vendor_bootimg_size(buf, &priv->vendor_boot_img_size)) {
151                 free(buf);
152                 return log_msg_ret("get vendor bootimg size", -EINVAL);
153         }
154
155         free(buf);
156
157         return 0;
158 }
159
160 static int android_read_slot_from_bcb(struct bootflow *bflow, bool decrement)
161 {
162         struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
163         struct android_priv *priv = bflow->bootmeth_priv;
164         struct disk_partition misc;
165         char slot_suffix[3];
166         int ret;
167
168         if (!CONFIG_IS_ENABLED(ANDROID_AB)) {
169                 priv->slot = NULL;
170                 return 0;
171         }
172
173         ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc);
174         if (ret < 0)
175                 return log_msg_ret("part", ret);
176
177         ret = ab_select_slot(desc, &misc, decrement);
178         if (ret < 0)
179                 return log_msg_ret("slot", ret);
180
181         priv->slot = malloc(SLOT_LEN);
182         priv->slot[0] = BOOT_SLOT_NAME(ret);
183         priv->slot[1] = '\0';
184
185         sprintf(slot_suffix, "_%s", priv->slot);
186         ret = bootflow_cmdline_set_arg(bflow, "androidboot.slot_suffix",
187                                        slot_suffix, false);
188         if (ret < 0)
189                 return log_msg_ret("cmdl", ret);
190
191         return 0;
192 }
193
194 static int configure_serialno(struct bootflow *bflow)
195 {
196         char *serialno = env_get("serial#");
197
198         if (!serialno)
199                 return log_msg_ret("serial", -ENOENT);
200
201         return bootflow_cmdline_set_arg(bflow, "androidboot.serialno", serialno, false);
202 }
203
204 static int configure_bootloader_version(struct bootflow *bflow)
205 {
206         return bootflow_cmdline_set_arg(bflow, "androidboot.bootloader",
207                                         PLAIN_VERSION, false);
208 }
209
210 static int android_read_bootflow(struct udevice *dev, struct bootflow *bflow)
211 {
212         struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
213         struct disk_partition misc;
214         struct android_priv *priv;
215         char command[BCB_FIELD_COMMAND_SZ];
216         int ret;
217
218         bflow->state = BOOTFLOWST_MEDIA;
219
220         /*
221          * bcb_find_partition_and_load() will print errors to stdout
222          * if BCB_PART_NAME is not found. To avoid that, check if the
223          * partition exists first.
224          */
225         ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc);
226         if (ret < 0)
227                 return log_msg_ret("part", ret);
228
229         ret = bcb_find_partition_and_load("mmc", desc->devnum, BCB_PART_NAME);
230         if (ret < 0)
231                 return log_msg_ret("bcb load", ret);
232
233         ret = bcb_get(BCB_FIELD_COMMAND, command, sizeof(command));
234         if (ret < 0)
235                 return log_msg_ret("bcb read", ret);
236
237         priv = malloc(sizeof(struct android_priv));
238         if (!priv)
239                 return log_msg_ret("buf", -ENOMEM);
240
241         if (!strcmp("bootonce-bootloader", command)) {
242                 priv->boot_mode = ANDROID_BOOT_MODE_BOOTLOADER;
243                 bflow->os_name = strdup("Android (bootloader)");
244         } else if (!strcmp("boot-fastboot", command)) {
245                 priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY;
246                 bflow->os_name = strdup("Android (fastbootd)");
247         } else if (!strcmp("boot-recovery", command)) {
248                 priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY;
249                 bflow->os_name = strdup("Android (recovery)");
250         } else {
251                 priv->boot_mode = ANDROID_BOOT_MODE_NORMAL;
252                 bflow->os_name = strdup("Android");
253         }
254         if (!bflow->os_name)
255                 return log_msg_ret("os", -ENOMEM);
256
257         if (priv->boot_mode == ANDROID_BOOT_MODE_BOOTLOADER) {
258                 /* Clear BCB */
259                 memset(command, 0, sizeof(command));
260                 ret = bcb_set(BCB_FIELD_COMMAND, command);
261                 if (ret < 0) {
262                         free(priv);
263                         return log_msg_ret("bcb set", ret);
264                 }
265                 ret = bcb_store();
266                 if (ret < 0) {
267                         free(priv);
268                         return log_msg_ret("bcb store", ret);
269                 }
270
271                 bflow->bootmeth_priv = priv;
272                 bflow->state = BOOTFLOWST_READY;
273                 return 0;
274         }
275
276         bflow->bootmeth_priv = priv;
277
278         /* For recovery and normal boot, we need to scan the partitions */
279         ret = android_read_slot_from_bcb(bflow, false);
280         if (ret < 0) {
281                 log_err("read slot: %d", ret);
282                 goto free_priv;
283         }
284
285         ret = scan_boot_part(bflow->blk, priv);
286         if (ret < 0) {
287                 log_debug("scan boot failed: err=%d\n", ret);
288                 goto free_priv;
289         }
290
291         if (priv->header_version >= 3) {
292                 ret = scan_vendor_boot_part(bflow->blk, priv);
293                 if (ret < 0) {
294                         log_debug("scan vendor_boot failed: err=%d\n", ret);
295                         goto free_priv;
296                 }
297         }
298
299         /*
300          * Ignoring return code for the following configurations:
301          * these are not mandatory for booting.
302          */
303         configure_serialno(bflow);
304         configure_bootloader_version(bflow);
305
306         if (priv->boot_mode == ANDROID_BOOT_MODE_NORMAL && priv->slot) {
307                 ret = bootflow_cmdline_set_arg(bflow, "androidboot.force_normal_boot",
308                                                "1", false);
309                 if (ret < 0) {
310                         log_debug("normal_boot %d", ret);
311                         goto free_priv;
312                 }
313         }
314
315         bflow->state = BOOTFLOWST_READY;
316
317         return 0;
318
319  free_priv:
320         free(priv);
321         bflow->bootmeth_priv = NULL;
322         return ret;
323 }
324
325 static int android_read_file(struct udevice *dev, struct bootflow *bflow,
326                              const char *file_path, ulong addr,
327                              enum bootflow_img_t type, ulong *sizep)
328 {
329         /*
330          * Reading individual files is not supported since we only
331          * operate on whole mmc devices (because we require multiple partitions)
332          */
333         return log_msg_ret("Unsupported", -ENOSYS);
334 }
335
336 /**
337  * read_slotted_partition() - Read a partition by appending a slot suffix
338  *
339  * Most modern Android devices use Seamless Updates, where each partition
340  * is duplicated. For example, the boot partition has boot_a and boot_b.
341  * For more information, see:
342  * https://source.android.com/docs/core/ota/ab
343  * https://source.android.com/docs/core/ota/ab/ab_implement
344  *
345  * @blk: Block device to read
346  * @name: Partition name to read
347  * @slot: Nul-terminated slot suffixed to partition name ("a\0" or "b\0")
348  * @image_size: Image size in bytes used when reading the partition
349  * @addr: Address where the partition content is loaded into
350  * Return: 0 if OK, negative errno on failure.
351  */
352 static int read_slotted_partition(struct blk_desc *desc, const char *const name,
353                                   const char slot[2], ulong image_size, ulong addr)
354 {
355         struct disk_partition partition;
356         char partname[PART_NAME_LEN];
357         size_t partname_len;
358         ulong num_blks = DIV_ROUND_UP(image_size, desc->blksz);
359         int ret;
360         u32 n;
361
362         /*
363          * Ensure name fits in partname.
364          * For A/B, it should be <name>_<slot>\0
365          * For non A/B, it should be <name>\0
366          */
367         if (CONFIG_IS_ENABLED(ANDROID_AB))
368                 partname_len = PART_NAME_LEN - 2 - 1;
369         else
370                 partname_len = PART_NAME_LEN - 1;
371
372         if (strlen(name) > partname_len)
373                 return log_msg_ret("name too long", -EINVAL);
374
375         if (slot)
376                 sprintf(partname, "%s_%s", name, slot);
377         else
378                 sprintf(partname, "%s", name);
379
380         ret = part_get_info_by_name(desc, partname, &partition);
381         if (ret < 0)
382                 return log_msg_ret("part", ret);
383
384         n = blk_dread(desc, partition.start, num_blks, map_sysmem(addr, 0));
385         if (n < num_blks)
386                 return log_msg_ret("part read", -EIO);
387
388         return 0;
389 }
390
391 #if CONFIG_IS_ENABLED(AVB_VERIFY)
392 static int avb_append_commandline_arg(struct bootflow *bflow, char *arg)
393 {
394         char *key = strsep(&arg, "=");
395         char *value = arg;
396         int ret;
397
398         ret = bootflow_cmdline_set_arg(bflow, key, value, false);
399         if (ret < 0)
400                 return log_msg_ret("avb cmdline", ret);
401
402         return 0;
403 }
404
405 static int avb_append_commandline(struct bootflow *bflow, char *cmdline)
406 {
407         char *arg = strsep(&cmdline, " ");
408         int ret;
409
410         while (arg) {
411                 ret = avb_append_commandline_arg(bflow, arg);
412                 if (ret < 0)
413                         return ret;
414
415                 arg = strsep(&cmdline, " ");
416         }
417
418         return 0;
419 }
420
421 static int run_avb_verification(struct bootflow *bflow)
422 {
423         struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
424         struct android_priv *priv = bflow->bootmeth_priv;
425         const char * const requested_partitions[] = {"boot", "vendor_boot", NULL};
426         struct AvbOps *avb_ops;
427         AvbSlotVerifyResult result;
428         AvbSlotVerifyData *out_data;
429         enum avb_boot_state boot_state;
430         char *extra_args;
431         char slot_suffix[3] = "";
432         bool unlocked = false;
433         int ret;
434
435         avb_ops = avb_ops_alloc(desc->devnum);
436         if (!avb_ops)
437                 return log_msg_ret("avb ops", -ENOMEM);
438
439         if (priv->slot)
440                 sprintf(slot_suffix, "_%s", priv->slot);
441
442         ret = avb_ops->read_is_device_unlocked(avb_ops, &unlocked);
443         if (ret != AVB_IO_RESULT_OK)
444                 return log_msg_ret("avb lock", -EIO);
445
446         result = avb_slot_verify(avb_ops,
447                                  requested_partitions,
448                                  slot_suffix,
449                                  unlocked,
450                                  AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
451                                  &out_data);
452
453         if (!unlocked) {
454                 /* When device is locked, we only accept AVB_SLOT_VERIFY_RESULT_OK */
455                 if (result != AVB_SLOT_VERIFY_RESULT_OK) {
456                         printf("Verification failed, reason: %s\n",
457                                str_avb_slot_error(result));
458                         avb_slot_verify_data_free(out_data);
459                         return log_msg_ret("avb verify", -EIO);
460                 }
461                 boot_state = AVB_GREEN;
462         } else {
463                 /* When device is unlocked, we also accept verification errors */
464                 if (result != AVB_SLOT_VERIFY_RESULT_OK &&
465                     result != AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION) {
466                         printf("Unlocked verification failed, reason: %s\n",
467                                str_avb_slot_error(result));
468                         avb_slot_verify_data_free(out_data);
469                         return log_msg_ret("avb verify unlocked", -EIO);
470                 }
471                 boot_state = AVB_ORANGE;
472         }
473
474         extra_args = avb_set_state(avb_ops, boot_state);
475         if (extra_args) {
476                 /* extra_args will be modified after this. This is fine */
477                 ret = avb_append_commandline_arg(bflow, extra_args);
478                 if (ret < 0)
479                         goto free_out_data;
480         }
481
482         if (result == AVB_SLOT_VERIFY_RESULT_OK) {
483                 ret = avb_append_commandline(bflow, out_data->cmdline);
484                 if (ret < 0)
485                         goto free_out_data;
486         }
487
488         return 0;
489
490  free_out_data:
491         if (out_data)
492                 avb_slot_verify_data_free(out_data);
493
494         return log_msg_ret("avb cmdline", ret);
495 }
496 #else
497 static int run_avb_verification(struct bootflow *bflow)
498 {
499         int ret;
500
501         /* When AVB is unsupported, pass ORANGE state  */
502         ret = bootflow_cmdline_set_arg(bflow,
503                                        "androidboot.verifiedbootstate",
504                                        "orange", false);
505         if (ret < 0)
506                 return log_msg_ret("avb cmdline", ret);
507
508         return 0;
509 }
510 #endif /* AVB_VERIFY */
511
512 static int boot_android_normal(struct bootflow *bflow)
513 {
514         struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
515         struct android_priv *priv = bflow->bootmeth_priv;
516         int ret;
517         ulong loadaddr = env_get_hex("loadaddr", 0);
518         ulong vloadaddr = env_get_hex("vendor_boot_comp_addr_r", 0);
519
520         ret = run_avb_verification(bflow);
521         if (ret < 0)
522                 return log_msg_ret("avb", ret);
523
524         /* Read slot once more to decrement counter from BCB */
525         ret = android_read_slot_from_bcb(bflow, true);
526         if (ret < 0)
527                 return log_msg_ret("read slot", ret);
528
529         ret = read_slotted_partition(desc, "boot", priv->slot, priv->boot_img_size,
530                                      loadaddr);
531         if (ret < 0)
532                 return log_msg_ret("read boot", ret);
533
534         if (priv->header_version >= 3) {
535                 ret = read_slotted_partition(desc, "vendor_boot", priv->slot,
536                                              priv->vendor_boot_img_size, vloadaddr);
537                 if (ret < 0)
538                         return log_msg_ret("read vendor_boot", ret);
539                 set_avendor_bootimg_addr(vloadaddr);
540         }
541         set_abootimg_addr(loadaddr);
542
543         if (priv->slot)
544                 free(priv->slot);
545
546         ret = bootm_boot_start(loadaddr, bflow->cmdline);
547
548         return log_msg_ret("boot", ret);
549 }
550
551 static int boot_android_recovery(struct bootflow *bflow)
552 {
553         int ret;
554
555         ret = boot_android_normal(bflow);
556
557         return log_msg_ret("boot", ret);
558 }
559
560 static int boot_android_bootloader(struct bootflow *bflow)
561 {
562         int ret;
563
564         ret = run_command("fastboot usb 0", 0);
565         do_reset(NULL, 0, 0, NULL);
566
567         return log_msg_ret("boot", ret);
568 }
569
570 static int android_boot(struct udevice *dev, struct bootflow *bflow)
571 {
572         struct android_priv *priv = bflow->bootmeth_priv;
573         int ret;
574
575         switch (priv->boot_mode) {
576         case ANDROID_BOOT_MODE_NORMAL:
577                 ret = boot_android_normal(bflow);
578                 break;
579         case ANDROID_BOOT_MODE_RECOVERY:
580                 ret = boot_android_recovery(bflow);
581                 break;
582         case ANDROID_BOOT_MODE_BOOTLOADER:
583                 ret = boot_android_bootloader(bflow);
584                 break;
585         default:
586                 printf("ANDROID: Unknown boot mode %d. Running fastboot...\n",
587                        priv->boot_mode);
588                 boot_android_bootloader(bflow);
589                 /* Tell we failed to boot since boot mode is unknown */
590                 ret = -EFAULT;
591         }
592
593         return ret;
594 }
595
596 static int android_bootmeth_bind(struct udevice *dev)
597 {
598         struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
599
600         plat->desc = "Android boot";
601         plat->flags = BOOTMETHF_ANY_PART;
602
603         return 0;
604 }
605
606 static struct bootmeth_ops android_bootmeth_ops = {
607         .check          = android_check,
608         .read_bootflow  = android_read_bootflow,
609         .read_file      = android_read_file,
610         .boot           = android_boot,
611 };
612
613 static const struct udevice_id android_bootmeth_ids[] = {
614         { .compatible = "u-boot,android" },
615         { }
616 };
617
618 U_BOOT_DRIVER(bootmeth_android) = {
619         .name           = "bootmeth_android",
620         .id             = UCLASS_BOOTMETH,
621         .of_match       = android_bootmeth_ids,
622         .ops            = &android_bootmeth_ops,
623         .bind           = android_bootmeth_bind,
624 };
This page took 0.06095 seconds and 4 git commands to generate.