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