xref: /rk3399_rockchip-uboot/common/android_ab.c (revision 11b25801bd4e56894e87abd893d0b2c620bc8e17)
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 #include <android_ab.h>
8 
9 #include <android_bootloader_message.h>
10 #include <android_image.h>
11 #include <boot_rkimg.h>
12 #include <common.h>
13 #include <malloc.h>
14 #include <android_avb/avb_ops_user.h>
15 #include <android_avb/rk_avb_ops_user.h>
16 #include <u-boot/crc.h>
17 #include <boot_rkimg.h>
18 
19 /** android_boot_control_compute_crc - Compute the CRC-32 of the bootloader
20  * control struct. Only the bytes up to the crc32_le field are considered for
21  * the CRC-32 calculation.
22  */
23 static uint32_t android_boot_control_compute_crc(
24 		struct android_bootloader_control *abc)
25 {
26 	return crc32(0, (void *)abc, offsetof(typeof(*abc), crc32_le));
27 }
28 
29 /** android_boot_control_default - Initialize android_bootloader_control to the
30  * default value which allows to boot all slots in order from the first one.
31  * This value should be used when the bootloader message is corrupted, but not
32  * when a valid message indicates that all slots are unbootable.
33  */
34 void android_boot_control_default(struct android_bootloader_control *abc)
35 {
36 	int i;
37 	const struct android_slot_metadata metadata = {
38 		.priority = 15,
39 		.tries_remaining = 7,
40 		.successful_boot = 0,
41 		.verity_corrupted = 0,
42 		.reserved = 0
43 	};
44 	memcpy(abc->slot_suffix, "a\0\0\0", 4);
45 	abc->magic = ANDROID_BOOT_CTRL_MAGIC;
46 	abc->version = ANDROID_BOOT_CTRL_VERSION;
47 	abc->nb_slot = ARRAY_SIZE(abc->slot_info);
48 	memset(abc->reserved0, 0, sizeof(abc->reserved0));
49 	for (i = 0; i < abc->nb_slot; ++i) {
50 		abc->slot_info[i] = metadata;
51 	}
52 	memset(abc->reserved1, 0, sizeof(abc->reserved1));
53 	abc->crc32_le = android_boot_control_compute_crc(abc);
54 }
55 
56 /** android_boot_control_create_from_disk
57  * Load the boot_control struct from disk into newly allocated memory. This
58  * function allocates and returns an integer number of disk blocks, based on the
59  * block size of the passed device to help performing a read-modify-write
60  * operation on the boot_control struct. The boot_control struct offset (2 KiB)
61  * must be a multiple of the device block size, for simplicity.
62  * @dev_desc: device where to read the boot_control struct from.
63  * @part_info: partition in 'dev_desc' where to read from, normally the "misc"
64  *             partition should be used.
65  */
66 static void *android_boot_control_create_from_disk(
67 		struct blk_desc *dev_desc,
68 		const disk_partition_t *part_info)
69 {
70 	ulong abc_offset, abc_blocks;
71 	void *buf;
72 
73 	abc_offset = offsetof(struct android_bootloader_message_ab,
74 			      slot_suffix);
75 	if (abc_offset % part_info->blksz) {
76 		printf("ANDROID: Boot control block not block aligned.\n");
77 		return NULL;
78 	}
79 	abc_offset /= part_info->blksz;
80 
81 	abc_blocks = DIV_ROUND_UP(sizeof(struct android_bootloader_control),
82 				  part_info->blksz);
83 	if (abc_offset + abc_blocks > part_info->size) {
84 		printf("ANDROID: boot control partition too small. Need at"
85 		       " least %lu blocks but have %lu blocks.\n",
86 		       abc_offset + abc_blocks, part_info->size);
87 		return NULL;
88 	}
89 	buf = malloc(abc_blocks * part_info->blksz);
90 	if (!buf)
91 		return NULL;
92 
93 	if (blk_dread(dev_desc, part_info->start + abc_offset, abc_blocks,
94 		      buf) != abc_blocks) {
95 		printf("ANDROID: Could not read from boot control partition\n");
96 		free(buf);
97 		return NULL;
98 	}
99 	debug("ANDROID: Loaded ABC, %lu blocks.\n", abc_blocks);
100 	return buf;
101 }
102 
103 /** android_boot_control_store
104  * Store the loaded boot_control block back to the same location it was read
105  * from with android_boot_control_create_from_misc().
106  *
107  * @abc_data_block: pointer to the boot_control struct and the extra bytes after
108  *                  it up to the nearest block boundary.
109  * @dev_desc: device where we should write the boot_control struct.
110  * @part_info: partition on the 'dev_desc' where to write.
111  * @return 0 on success and -1 on error.
112  */
113 static int android_boot_control_store(void *abc_data_block,
114 				      struct blk_desc *dev_desc,
115 				      const disk_partition_t *part_info)
116 {
117 	ulong abc_offset, abc_blocks;
118 
119 	abc_offset = offsetof(struct android_bootloader_message_ab,
120 			      slot_suffix) / part_info->blksz;
121 	abc_blocks = DIV_ROUND_UP(sizeof(struct android_bootloader_control),
122 				  part_info->blksz);
123 	if (blk_dwrite(dev_desc, part_info->start + abc_offset, abc_blocks,
124 		       abc_data_block) != abc_blocks) {
125 		printf("ANDROID: Could not write back the misc partition\n");
126 		return -1;
127 	}
128 	return 0;
129 }
130 
131 /** android_boot_compare_slots - compares two slots returning which slot is
132  * should we boot from among the two.
133  * @a: The first bootable slot metadata
134  * @b: The second bootable slot metadata
135  * @return negative if the slot "a" is better, positive of the slot "b" is
136  * better or 0 if they are equally good.
137  */
138 static int android_ab_compare_slots(const struct android_slot_metadata *a,
139 				    const struct android_slot_metadata *b)
140 {
141 	/* Higher priority is better */
142 	if (a->priority != b->priority)
143 		return b->priority - a->priority;
144 
145 	/* Higher successful_boot value is better, in case of same priority. */
146 	if (a->successful_boot != b->successful_boot)
147 		return b->successful_boot - a->successful_boot;
148 
149 	/* Higher tries_remaining is better to ensure round-robin. */
150 	if (a->tries_remaining != b->tries_remaining)
151 		return b->tries_remaining - a->tries_remaining;
152 
153 	return 0;
154 }
155 
156 int android_ab_select(struct blk_desc *dev_desc, disk_partition_t *part_info)
157 {
158 	struct android_bootloader_control *abc;
159 	u32 crc32_le;
160 	int slot, i;
161 	bool store_needed = false;
162 	char slot_suffix[4];
163 
164 	abc = android_boot_control_create_from_disk(dev_desc, part_info);
165 	if (!abc) {
166 		/* This condition represents an actual problem with the code
167 		 * or the board setup, like an invalid partition information.
168 		 * Signal a repair mode and do not try to boot from either
169 		 * slot.
170 		 */
171 		return -1;
172 	}
173 
174 	crc32_le = android_boot_control_compute_crc(abc);
175 	if (abc->crc32_le != crc32_le) {
176 		printf("ANDROID: Invalid CRC-32 (expected %.8x, found %.8x), "
177 		       "re-initializing A/B metadata.\n",
178 		       crc32_le, abc->crc32_le);
179 		android_boot_control_default(abc);
180 		store_needed = true;
181 	}
182 
183 	if (abc->magic != ANDROID_BOOT_CTRL_MAGIC) {
184 		printf("ANDROID: Unknown A/B metadata: %.8x\n", abc->magic);
185 		free(abc);
186 		return -1;
187 	}
188 
189 	if (abc->version > ANDROID_BOOT_CTRL_VERSION) {
190 		printf("ANDROID: Unsupported A/B metadata version: %.8x\n",
191 		       abc->version);
192 		free(abc);
193 		return -1;
194 	}
195 
196 	/* At this point a valid boot control metadata is stored in abc,
197 	 * followed by other reserved data in the same block.
198 	 * We select a with the higher priority slot that
199 	 *  - is not marked as corrupted and
200 	 *  - either has tries_remaining > 0 or successful_boot is true.
201 	 * If the slot selected has a false successful_boot, we also decrement
202 	 * the tries_remaining until it eventually becomes unbootable because
203 	 * tries_remaining reaches 0. This mechanism produces a bootloader
204 	 * induced rollback, typically right after a failed update.
205 	 */
206 
207 	/* Safety check: limit the number of slots. */
208 	if (abc->nb_slot > ARRAY_SIZE(abc->slot_info)) {
209 		abc->nb_slot = ARRAY_SIZE(abc->slot_info);
210 		store_needed = true;
211 	}
212 
213 	slot = -1;
214 	for (i = 0; i < abc->nb_slot; ++i) {
215 		if (abc->slot_info[i].verity_corrupted ||
216 		    !abc->slot_info[i].tries_remaining) {
217 			debug("ANDROID: unbootable slot %d tries: %d, "
218 			      "corrupt: %d\n",
219 			      i,
220 			      abc->slot_info[i].tries_remaining,
221 			      abc->slot_info[i].verity_corrupted);
222 			continue;
223 		}
224 		debug("ANDROID: bootable slot %d pri: %d, tries: %d, "
225 		      "corrupt: %d, successful: %d\n",
226 		      i,
227 		      abc->slot_info[i].priority,
228 		      abc->slot_info[i].tries_remaining,
229 		      abc->slot_info[i].verity_corrupted,
230 		      abc->slot_info[i].successful_boot);
231 
232 		if (slot < 0 ||
233 		    android_ab_compare_slots(&abc->slot_info[i],
234 					     &abc->slot_info[slot]) < 0) {
235 			slot = i;
236 		}
237 	}
238 
239 	if (slot >= 0 && !abc->slot_info[slot].successful_boot) {
240 		printf("ANDROID: Attempting slot %c, tries remaining %d\n",
241 		       ANDROID_BOOT_SLOT_NAME(slot),
242 		       abc->slot_info[slot].tries_remaining);
243 		abc->slot_info[slot].tries_remaining--;
244 		store_needed = true;
245 	}
246 
247 	if (slot >= 0) {
248 		/* Legacy user-space requires this field to be set in the BCB.
249 		 * Newer releases load this the slot suffix from the command
250 		 * line or the device tree.
251 		 */
252 		memset(slot_suffix, 0, sizeof(slot_suffix));
253 		slot_suffix[0] = ANDROID_BOOT_SLOT_NAME(slot);
254 		if (memcmp(abc->slot_suffix, slot_suffix,
255 			   sizeof(slot_suffix))) {
256 			memcpy(abc->slot_suffix, slot_suffix,
257 			       sizeof(slot_suffix));
258 			store_needed = true;
259 		}
260 	}
261 
262 	if (store_needed) {
263 		abc->crc32_le = android_boot_control_compute_crc(abc);
264 		android_boot_control_store(abc, dev_desc, part_info);
265 	}
266 	free(abc);
267 
268 	if (slot < 0)
269 		return -1;
270 	return slot;
271 }
272 
273 int read_misc_virtual_ab_message(struct misc_virtual_ab_message *message)
274 {
275 	struct blk_desc *dev_desc;
276 	disk_partition_t part_info;
277 	u32 bcb_offset = (ANDROID_VIRTUAL_AB_METADATA_OFFSET_IN_MISC >> 9);
278 	int cnt, ret;
279 
280 	if (!message) {
281 		debug("%s: message is NULL!\n", __func__);
282 		return -1;
283 	}
284 
285 	dev_desc = rockchip_get_bootdev();
286 	if (!dev_desc) {
287 		debug("%s: dev_desc is NULL!\n", __func__);
288 		return -1;
289 	}
290 
291 	ret = part_get_info_by_name(dev_desc, PART_MISC, &part_info);
292 	if (ret < 0) {
293 		debug("%s: Could not found misc partition\n",
294 		       __func__);
295 		return -1;
296 	}
297 
298 	cnt = DIV_ROUND_UP(sizeof(struct misc_virtual_ab_message), dev_desc->blksz);
299 	if (blk_dread(dev_desc, part_info.start + bcb_offset, cnt, message) != cnt) {
300 		debug("%s: could not read from misc partition\n", __func__);
301 		return -1;
302 	}
303 
304 	return 0;
305 }
306 
307 int write_misc_virtual_ab_message(struct misc_virtual_ab_message *message)
308 {
309 	struct blk_desc *dev_desc;
310 	disk_partition_t part_info;
311 	u32 bcb_offset = (ANDROID_VIRTUAL_AB_METADATA_OFFSET_IN_MISC >> 9);
312 	int cnt, ret;
313 
314 	if (!message) {
315 		debug("%s: message is NULL!\n", __func__);
316 		return -1;
317 	}
318 
319 	dev_desc = rockchip_get_bootdev();
320 	if (!dev_desc) {
321 		debug("%s: dev_desc is NULL!\n", __func__);
322 		return -1;
323 	}
324 
325 	ret = part_get_info_by_name(dev_desc, PART_MISC, &part_info);
326 	if (ret < 0) {
327 		debug("%s: Could not found misc partition\n",
328 		       __func__);
329 		return -1;
330 	}
331 
332 	cnt = DIV_ROUND_UP(sizeof(struct misc_virtual_ab_message), dev_desc->blksz);
333 	ret = blk_dwrite(dev_desc, part_info.start + bcb_offset, cnt, message);
334 	if (ret != cnt)
335 		debug("%s: blk_dwrite write failed, ret=%d\n", __func__, ret);
336 
337 	return 0;
338 }
339 
340 int ab_is_support_dynamic_partition(struct blk_desc *dev_desc)
341 {
342 	disk_partition_t super_part_info;
343 	disk_partition_t boot_part_info;
344 	int part_num;
345 	int is_dp = 0;
346 	char *super_dp = NULL;
347 	char *super_info = "androidboot.super_partition=";
348 
349 	memset(&super_part_info, 0x0, sizeof(super_part_info));
350 	part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_SUPER,
351 					 &super_part_info);
352 	if (part_num < 0) {
353 		memset(&boot_part_info, 0x0, sizeof(boot_part_info));
354 		part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_BOOT,
355 						 &boot_part_info);
356 		if (part_num < 0) {
357 			is_dp = 0;
358 		} else {
359 			andr_img_hdr hdr;
360 			ulong hdr_blocks = sizeof(struct andr_img_hdr) /
361 			boot_part_info.blksz;
362 
363 			memset(&hdr, 0x0, sizeof(hdr));
364 			if (blk_dread(dev_desc, boot_part_info.start, hdr_blocks, &hdr) !=
365 				hdr_blocks) {
366 				is_dp = 0;
367 			} else {
368 				debug("hdr cmdline=%s\n", hdr.cmdline);
369 				super_dp = strstr(hdr.cmdline, super_info);
370 				if (super_dp)
371 					is_dp = 1;
372 				else
373 					is_dp = 0;
374 			}
375 		}
376 	} else {
377 		debug("Find super partition, the firmware support dynamic partition\n");
378 		is_dp = 1;
379 	}
380 
381 	debug("%s is_dp=%d\n", __func__, is_dp);
382 	return is_dp;
383 }
384 
385 static int get_partition_unique_uuid(char *partition,
386 				     char *guid_buf,
387 				     size_t guid_buf_size)
388 {
389 #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
390 	struct blk_desc *dev_desc;
391 	disk_partition_t part_info;
392 
393 	dev_desc = rockchip_get_bootdev();
394 	if (!dev_desc) {
395 		printf("%s: Could not find device\n", __func__);
396 		return -1;
397 	}
398 
399 	if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
400 		printf("Could not find \"%s\" partition\n", partition);
401 		return -1;
402 	}
403 
404 	if (guid_buf && guid_buf_size > 0)
405 		memcpy(guid_buf, part_info.uuid, guid_buf_size);
406 
407 	return 0;
408 #else
409 	printf("WARN: Get partition uuid requires CONFIG_PARTITION_UUIDS enabled\n");
410 	return -1;
411 #endif
412 }
413 
414 static void ab_update_root_uuid(void)
415 {
416 	/*
417 	 * In android a/b & avb process, the system.img is mandory and the
418 	 * "root=" will be added in vbmeta.img.
419 	 *
420 	 * In linux a/b & avb process, the system is NOT mandory and the
421 	 * "root=" will not be added in vbmeta.img but in kernel dts bootargs.
422 	 * (Parsed and dropped late, i.e. "root=" is not available now/always).
423 	 *
424 	 * To compatible with the above two processes, test the existence of
425 	 * "root=" and create it for linux ab & avb.
426 	 */
427 	char root_partuuid[70] = "root=PARTUUID=";
428 	char *boot_args = env_get("bootargs");
429 	char guid_buf[UUID_SIZE] = {0};
430 	struct blk_desc *dev_desc;
431 
432 	dev_desc = rockchip_get_bootdev();
433 	if (!dev_desc) {
434 		printf("%s: Could not find device\n", __func__);
435 		return;
436 	}
437 
438 	if (ab_is_support_dynamic_partition(dev_desc))
439 		return;
440 
441 	if (!strstr(boot_args, "root=")) {
442 		get_partition_unique_uuid(ANDROID_PARTITION_SYSTEM,
443 					  guid_buf, UUID_SIZE);
444 		strcat(root_partuuid, guid_buf);
445 		env_update("bootargs", root_partuuid);
446 	}
447 }
448 
449 void ab_update_root_partition(void)
450 {
451 	char *boot_args = env_get("bootargs");
452 	char root_part_dev[64] = {0};
453 	disk_partition_t part_info;
454 	struct blk_desc *dev_desc;
455 	const char *part_type;
456 	int part_num;
457 
458 	dev_desc = rockchip_get_bootdev();
459 	if (!dev_desc)
460 		return;
461 
462 	if (ab_is_support_dynamic_partition(dev_desc))
463 		return;
464 
465 	/* Get 'system' partition device number. */
466 	part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_SYSTEM, &part_info);
467 	if (part_num < 0) {
468 		printf("%s: Failed to get partition '%s'.\n", __func__, ANDROID_PARTITION_SYSTEM);
469 		return;
470 	}
471 
472 	/* Get partition type. */
473 	part_type = part_get_type(dev_desc);
474 	if (!part_type)
475 		return;
476 
477 	/* Judge the partition device type. */
478 	switch (dev_desc->if_type) {
479 	case IF_TYPE_MMC:
480 	case IF_TYPE_SCSI: /* scsi 0: UFS */
481 		if (strstr(part_type, "ENV"))
482 			snprintf(root_part_dev, 64, "root=/dev/mmcblk0p%d", part_num);
483 		else if (strstr(part_type, "EFI"))
484 			ab_update_root_uuid();
485 		break;
486 	case IF_TYPE_SPINAND:
487 		if (strstr(part_type, "ENV"))
488 			/* TODO */
489 			printf("%s: TODO: ENV partition for 'IF_TYPE_SPINAND'.\n", __func__);
490 		else if (strstr(part_type, "EFI"))
491 			ab_update_root_uuid();
492 		break;
493 	case IF_TYPE_MTD:
494 		if (dev_desc->devnum == BLK_MTD_NAND || dev_desc->devnum == BLK_MTD_SPI_NAND) {
495 			if (strstr(boot_args, "rootfstype=squashfs") || strstr(boot_args, "rootfstype=erofs"))
496 				snprintf(root_part_dev, 64, "ubi.mtd=%d root=/dev/ubiblock0_0", part_num - 1);
497 			else if (strstr(boot_args, "rootfstype=ubifs"))
498 				snprintf(root_part_dev, 64, "ubi.mtd=%d root=ubi0:system", part_num - 1);
499 		} else if (dev_desc->devnum == BLK_MTD_SPI_NOR) {
500 			snprintf(root_part_dev, 64, "root=/dev/mtdblock%d", part_num - 1);
501 		}
502 		break;
503 	default:
504 		ab_update_root_uuid();
505 		printf("Unknown part type, set default 'root=' with UUID.\n");
506 		return;
507 	}
508 
509 	env_update("bootargs", root_part_dev);
510 }
511 
512 int ab_get_slot_suffix(char *slot_suffix)
513 {
514 	/* TODO: get from pre-loader or misc partition */
515 	if (rk_avb_get_current_slot(slot_suffix)) {
516 		printf("rk_avb_get_current_slot() failed\n");
517 		return -1;
518 	}
519 
520 	if (slot_suffix[0] != '_') {
521 #ifndef CONFIG_ANDROID_AVB
522 		printf("###There is no bootable slot, bring up lastboot!###\n");
523 		if (rk_get_lastboot() == 1)
524 			memcpy(slot_suffix, "_b", 2);
525 		else if (rk_get_lastboot() == 0)
526 			memcpy(slot_suffix, "_a", 2);
527 		else
528 #endif
529 			return -1;
530 	}
531 
532 	return 0;
533 }
534 
535 int ab_decrease_tries(void)
536 {
537 	AvbABData ab_data_orig;
538 	AvbABData ab_data;
539 	char slot_suffix[3] = {0};
540 	AvbOps *ops;
541 	size_t slot_index = 0;
542 
543 	if (ab_get_slot_suffix(slot_suffix))
544 		return -1;
545 
546 	if (!strncmp(slot_suffix, "_a", 2))
547 		slot_index = 0;
548 	else if (!strncmp(slot_suffix, "_b", 2))
549 		slot_index = 1;
550 	else
551 		slot_index = 0;
552 
553 	ops = avb_ops_user_new();
554 	if (!ops) {
555 		printf("avb_ops_user_new() failed!\n");
556 		return -1;
557 	}
558 
559 	if (load_metadata(ops->ab_ops, &ab_data, &ab_data_orig)) {
560 		printf("Can not load metadata\n");
561 		return -1;
562 	}
563 
564 	/* ... and decrement tries remaining, if applicable. */
565 	if (!ab_data.slots[slot_index].successful_boot &&
566 	    ab_data.slots[slot_index].tries_remaining > 0)
567 		ab_data.slots[slot_index].tries_remaining -= 1;
568 
569 	if (save_metadata_if_changed(ops->ab_ops, &ab_data, &ab_data_orig)) {
570 		printf("Can not save metadata\n");
571 		return -1;
572 	}
573 
574 	return 0;
575 }
576 
577 /*
578  * In android A/B system, there is no recovery partition,
579  * but in the linux system, we need the recovery to update system.
580  * This function is used to find firmware in recovery partition
581  * when enable CONFIG_ANDROID_AB.
582  */
583 bool ab_can_find_recovery_part(void)
584 {
585 	disk_partition_t part_info;
586 	struct blk_desc *dev_desc;
587 	int part_num;
588 
589 	dev_desc = rockchip_get_bootdev();
590 	if (!dev_desc) {
591 		printf("%s: Could not find device\n", __func__);
592 		return false;
593 	}
594 
595 	part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_RECOVERY,
596 					 &part_info);
597 	if (part_num < 0)
598 		return false;
599 	else
600 		return true;
601 }
602