xref: /OK3568_Linux_fs/u-boot/common/android_ab.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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  */
android_boot_control_compute_crc(struct android_bootloader_control * abc)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  */
android_boot_control_default(struct android_bootloader_control * abc)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  */
android_boot_control_create_from_disk(struct blk_desc * dev_desc,const disk_partition_t * part_info)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  */
android_boot_control_store(void * abc_data_block,struct blk_desc * dev_desc,const disk_partition_t * part_info)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  */
android_ab_compare_slots(const struct android_slot_metadata * a,const struct android_slot_metadata * b)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 
android_ab_select(struct blk_desc * dev_desc,disk_partition_t * part_info)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 
read_misc_virtual_ab_message(struct misc_virtual_ab_message * message)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 
write_misc_virtual_ab_message(struct misc_virtual_ab_message * message)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 
ab_is_support_dynamic_partition(struct blk_desc * dev_desc)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 
get_partition_unique_uuid(char * partition,char * guid_buf,size_t guid_buf_size)385 static int get_partition_unique_uuid(char *partition,
386 				     char *guid_buf,
387 				     size_t guid_buf_size)
388 {
389 	struct blk_desc *dev_desc;
390 	disk_partition_t part_info;
391 
392 	dev_desc = rockchip_get_bootdev();
393 	if (!dev_desc) {
394 		printf("%s: Could not find device\n", __func__);
395 		return -1;
396 	}
397 
398 	if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
399 		printf("Could not find \"%s\" partition\n", partition);
400 		return -1;
401 	}
402 
403 	if (guid_buf && guid_buf_size > 0)
404 		memcpy(guid_buf, part_info.uuid, guid_buf_size);
405 
406 	return 0;
407 }
408 
ab_update_root_uuid(void)409 static void ab_update_root_uuid(void)
410 {
411 	/*
412 	 * In android a/b & avb process, the system.img is mandory and the
413 	 * "root=" will be added in vbmeta.img.
414 	 *
415 	 * In linux a/b & avb process, the system is NOT mandory and the
416 	 * "root=" will not be added in vbmeta.img but in kernel dts bootargs.
417 	 * (Parsed and dropped late, i.e. "root=" is not available now/always).
418 	 *
419 	 * To compatible with the above two processes, test the existence of
420 	 * "root=" and create it for linux ab & avb.
421 	 */
422 	char root_partuuid[70] = "root=PARTUUID=";
423 	char *boot_args = env_get("bootargs");
424 	char guid_buf[UUID_SIZE] = {0};
425 	struct blk_desc *dev_desc;
426 
427 	dev_desc = rockchip_get_bootdev();
428 	if (!dev_desc) {
429 		printf("%s: Could not find device\n", __func__);
430 		return;
431 	}
432 
433 	if (ab_is_support_dynamic_partition(dev_desc))
434 		return;
435 
436 	if (!strstr(boot_args, "root=")) {
437 		get_partition_unique_uuid(ANDROID_PARTITION_SYSTEM,
438 					  guid_buf, UUID_SIZE);
439 		strcat(root_partuuid, guid_buf);
440 		env_update("bootargs", root_partuuid);
441 	}
442 }
443 
ab_update_root_partition(void)444 void ab_update_root_partition(void)
445 {
446 	char *boot_args = env_get("bootargs");
447 	char root_part_dev[64] = {0};
448 	disk_partition_t part_info;
449 	struct blk_desc *dev_desc;
450 	const char *part_type;
451 	int part_num;
452 
453 	dev_desc = rockchip_get_bootdev();
454 	if (!dev_desc)
455 		return;
456 
457 	if (ab_is_support_dynamic_partition(dev_desc))
458 		return;
459 
460 	/* Get 'system' partition device number. */
461 	part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_SYSTEM, &part_info);
462 	if (part_num < 0) {
463 		printf("%s: Failed to get partition '%s'.\n", __func__, ANDROID_PARTITION_SYSTEM);
464 		return;
465 	}
466 
467 	/* Get partition type. */
468 	part_type = part_get_type(dev_desc);
469 	if (!part_type)
470 		return;
471 
472 	/* Judge the partition device type. */
473 	switch (dev_desc->if_type) {
474 	case IF_TYPE_MMC:
475 		if (strstr(part_type, "ENV"))
476 			snprintf(root_part_dev, 64, "root=/dev/mmcblk0p%d", part_num);
477 		else if (strstr(part_type, "EFI"))
478 			ab_update_root_uuid();
479 		break;
480 	case IF_TYPE_MTD:
481 		if (dev_desc->devnum == BLK_MTD_NAND || dev_desc->devnum == BLK_MTD_SPI_NAND) {
482 			if (strstr(boot_args, "rootfstype=squashfs") || strstr(boot_args, "rootfstype=erofs"))
483 				snprintf(root_part_dev, 64, "ubi.mtd=%d root=/dev/ubiblock0_0", part_num - 1);
484 			else if (strstr(boot_args, "rootfstype=ubifs"))
485 				snprintf(root_part_dev, 64, "ubi.mtd=%d root=ubi0:system", part_num - 1);
486 		} else if (dev_desc->devnum == BLK_MTD_SPI_NOR) {
487 			snprintf(root_part_dev, 64, "root=/dev/mtdblock%d", part_num - 1);
488 		}
489 		break;
490 	default:
491 		printf("%s: Not found part type, failed to set root part device.\n", __func__);
492 		return;
493 	}
494 
495 	env_update("bootargs", root_part_dev);
496 }
497 
ab_get_slot_suffix(char * slot_suffix)498 int ab_get_slot_suffix(char *slot_suffix)
499 {
500 	/* TODO: get from pre-loader or misc partition */
501 	if (rk_avb_get_current_slot(slot_suffix)) {
502 		printf("rk_avb_get_current_slot() failed\n");
503 		return -1;
504 	}
505 
506 	if (slot_suffix[0] != '_') {
507 #ifndef CONFIG_ANDROID_AVB
508 		printf("###There is no bootable slot, bring up lastboot!###\n");
509 		if (rk_get_lastboot() == 1)
510 			memcpy(slot_suffix, "_b", 2);
511 		else if (rk_get_lastboot() == 0)
512 			memcpy(slot_suffix, "_a", 2);
513 		else
514 #endif
515 			return -1;
516 	}
517 
518 	return 0;
519 }
520 
ab_decrease_tries(void)521 int ab_decrease_tries(void)
522 {
523 	AvbABData ab_data_orig;
524 	AvbABData ab_data;
525 	char slot_suffix[3] = {0};
526 	AvbOps *ops;
527 	size_t slot_index = 0;
528 
529 	if (ab_get_slot_suffix(slot_suffix))
530 		return -1;
531 
532 	if (!strncmp(slot_suffix, "_a", 2))
533 		slot_index = 0;
534 	else if (!strncmp(slot_suffix, "_b", 2))
535 		slot_index = 1;
536 	else
537 		slot_index = 0;
538 
539 	ops = avb_ops_user_new();
540 	if (!ops) {
541 		printf("avb_ops_user_new() failed!\n");
542 		return -1;
543 	}
544 
545 	if (load_metadata(ops->ab_ops, &ab_data, &ab_data_orig)) {
546 		printf("Can not load metadata\n");
547 		return -1;
548 	}
549 
550 	/* ... and decrement tries remaining, if applicable. */
551 	if (!ab_data.slots[slot_index].successful_boot &&
552 	    ab_data.slots[slot_index].tries_remaining > 0)
553 		ab_data.slots[slot_index].tries_remaining -= 1;
554 
555 	if (save_metadata_if_changed(ops->ab_ops, &ab_data, &ab_data_orig)) {
556 		printf("Can not save metadata\n");
557 		return -1;
558 	}
559 
560 	return 0;
561 }
562 
563 /*
564  * In android A/B system, there is no recovery partition,
565  * but in the linux system, we need the recovery to update system.
566  * This function is used to find firmware in recovery partition
567  * when enable CONFIG_ANDROID_AB.
568  */
ab_can_find_recovery_part(void)569 bool ab_can_find_recovery_part(void)
570 {
571 	disk_partition_t part_info;
572 	struct blk_desc *dev_desc;
573 	int part_num;
574 
575 	dev_desc = rockchip_get_bootdev();
576 	if (!dev_desc) {
577 		printf("%s: Could not find device\n", __func__);
578 		return false;
579 	}
580 
581 	part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_RECOVERY,
582 					 &part_info);
583 	if (part_num < 0)
584 		return false;
585 	else
586 		return true;
587 }
588