1 /* 2 * (C) Copyright 2020 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 #include <common.h> 7 #include <malloc.h> 8 #include <mapmem.h> 9 #include <errno.h> 10 #include <command.h> 11 #include <blk.h> 12 #include <part.h> 13 #include <boot_rkimg.h> 14 #include <android_avb/rk_avb_ops_user.h> 15 16 static int safe_memcmp(const void *s1, const void *s2, size_t n) 17 { 18 const unsigned char *us1 = s1; 19 const unsigned char *us2 = s2; 20 int result = 0; 21 22 if (0 == n) 23 return 0; 24 25 /* 26 * Code snippet without data-dependent branch due to Nate Lawson 27 * (nate@root.org) of Root Labs. 28 */ 29 while (n--) 30 result |= *us1++ ^ *us2++; 31 32 return result != 0; 33 } 34 35 static uint32_t htobe32(uint32_t in) 36 { 37 union { 38 uint32_t word; 39 uint8_t bytes[4]; 40 } ret; 41 42 ret.bytes[0] = (in >> 24) & 0xff; 43 ret.bytes[1] = (in >> 16) & 0xff; 44 ret.bytes[2] = (in >> 8) & 0xff; 45 ret.bytes[3] = in & 0xff; 46 47 return ret.word; 48 } 49 50 static uint32_t be32toh(uint32_t in) 51 { 52 uint8_t *d = (uint8_t *)∈ 53 uint32_t ret; 54 55 ret = ((uint32_t)d[0]) << 24; 56 ret |= ((uint32_t)d[1]) << 16; 57 ret |= ((uint32_t)d[2]) << 8; 58 ret |= ((uint32_t)d[3]); 59 60 return ret; 61 } 62 63 static void slot_set_unbootable(AvbABSlotData* slot) 64 { 65 slot->priority = 0; 66 slot->tries_remaining = 0; 67 slot->successful_boot = 0; 68 } 69 70 /* Ensure all unbootable and/or illegal states are marked as the 71 * canonical 'unbootable' state, e.g. priority=0, tries_remaining=0, 72 * and successful_boot=0. 73 */ 74 static void slot_normalize(AvbABSlotData* slot) 75 { 76 if (slot->priority > 0) { 77 if (slot->tries_remaining == 0 && !slot->successful_boot) { 78 /* We've exhausted all tries -> unbootable. */ 79 slot_set_unbootable(slot); 80 } 81 if (slot->tries_remaining > 0 && slot->successful_boot) { 82 /* Illegal state - avb_ab_mark_slot_successful() will clear 83 * tries_remaining when setting successful_boot. 84 */ 85 slot_set_unbootable(slot); 86 } 87 } else { 88 slot_set_unbootable(slot); 89 } 90 } 91 92 /* Writes A/B metadata to disk only if it has changed - returns 93 * AVB_IO_RESULT_OK on success, error code otherwise. 94 */ 95 AvbIOResult save_metadata_if_changed(AvbABOps* ab_ops, 96 AvbABData* ab_data, 97 AvbABData* ab_data_orig) 98 { 99 if (safe_memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) { 100 debug("Writing A/B metadata to disk.\n"); 101 return ab_ops->write_ab_metadata(ab_ops, ab_data); 102 } 103 return AVB_IO_RESULT_OK; 104 } 105 106 bool avb_ab_data_verify_and_byteswap(const AvbABData* src, AvbABData* dest) { 107 /* Ensure magic is correct. */ 108 if (safe_memcmp(src->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) { 109 printf("Magic is incorrect.\n"); 110 return false; 111 } 112 113 memcpy(dest, src, sizeof(AvbABData)); 114 dest->crc32 = be32toh(dest->crc32); 115 116 /* Ensure we don't attempt to access any fields if the major version 117 * is not supported. 118 */ 119 if (dest->version_major > AVB_AB_MAJOR_VERSION) { 120 printf("No support for given major version.\n"); 121 return false; 122 } 123 124 /* Bail if CRC32 doesn't match. */ 125 if (dest->crc32 != 126 crc32(0, (const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))) { 127 printf("CRC32 does not match.\n"); 128 return false; 129 } 130 131 return true; 132 } 133 134 void avb_ab_data_update_crc_and_byteswap(const AvbABData* src, 135 AvbABData* dest) 136 { 137 memcpy(dest, src, sizeof(AvbABData)); 138 dest->crc32 = htobe32(crc32(0, (const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))); 139 } 140 141 void avb_ab_data_init(AvbABData* data) 142 { 143 memset(data, '\0', sizeof(AvbABData)); 144 memcpy(data->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN); 145 data->version_major = AVB_AB_MAJOR_VERSION; 146 data->version_minor = AVB_AB_MINOR_VERSION; 147 data->last_boot = 0; 148 data->slots[0].priority = AVB_AB_MAX_PRIORITY; 149 data->slots[0].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; 150 data->slots[0].successful_boot = 0; 151 data->slots[1].priority = AVB_AB_MAX_PRIORITY - 1; 152 data->slots[1].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; 153 data->slots[1].successful_boot = 0; 154 } 155 156 /* The AvbABData struct is stored 2048 bytes into the 'misc' partition 157 * following the 'struct bootloader_message' field. The struct is 158 * compatible with the guidelines in bootable/recovery/bootloader.h - 159 * e.g. it is stored in the |slot_suffix| field, starts with a 160 * NUL-byte, and is 32 bytes long. 161 */ 162 #define AB_METADATA_MISC_PARTITION_OFFSET 2048 163 164 AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data) 165 { 166 AvbOps* ops = ab_ops->ops; 167 AvbABData serialized; 168 AvbIOResult io_ret; 169 size_t num_bytes_read; 170 171 io_ret = ops->read_from_partition(ops, 172 "misc", 173 AB_METADATA_MISC_PARTITION_OFFSET, 174 sizeof(AvbABData), 175 &serialized, 176 &num_bytes_read); 177 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 178 return AVB_IO_RESULT_ERROR_OOM; 179 } else if (io_ret != AVB_IO_RESULT_OK || 180 num_bytes_read != sizeof(AvbABData)) { 181 printf("Error reading A/B metadata.\n"); 182 return AVB_IO_RESULT_ERROR_IO; 183 } 184 185 if (!avb_ab_data_verify_and_byteswap(&serialized, data)) { 186 printf("Error validating A/B metadata from disk. " 187 "Resetting and writing new A/B metadata to disk.\n"); 188 avb_ab_data_init(data); 189 return avb_ab_data_write(ab_ops, data); 190 } 191 192 return AVB_IO_RESULT_OK; 193 } 194 195 AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data) 196 { 197 AvbOps* ops = ab_ops->ops; 198 AvbABData serialized; 199 AvbIOResult io_ret; 200 201 avb_ab_data_update_crc_and_byteswap(data, &serialized); 202 io_ret = ops->write_to_partition(ops, 203 "misc", 204 AB_METADATA_MISC_PARTITION_OFFSET, 205 sizeof(AvbABData), 206 &serialized); 207 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 208 return AVB_IO_RESULT_ERROR_OOM; 209 } else if (io_ret != AVB_IO_RESULT_OK) { 210 printf("Error writing A/B metadata.\n"); 211 return AVB_IO_RESULT_ERROR_IO; 212 } 213 return AVB_IO_RESULT_OK; 214 } 215 216 /* Helper function to load metadata - returns AVB_IO_RESULT_OK on 217 * success, error code otherwise. 218 */ 219 AvbIOResult load_metadata(AvbABOps* ab_ops, 220 AvbABData* ab_data, 221 AvbABData* ab_data_orig) { 222 AvbIOResult io_ret; 223 224 io_ret = ab_ops->read_ab_metadata(ab_ops, ab_data); 225 if (io_ret != AVB_IO_RESULT_OK) { 226 printf("I/O error while loading A/B metadata.\n"); 227 return io_ret; 228 } 229 *ab_data_orig = *ab_data; 230 231 /* Ensure data is normalized, e.g. illegal states will be marked as 232 * unbootable and all unbootable states are represented with 233 * (priority=0, tries_remaining=0, successful_boot=0). 234 */ 235 slot_normalize(&ab_data->slots[0]); 236 slot_normalize(&ab_data->slots[1]); 237 return AVB_IO_RESULT_OK; 238 } 239 240 int rk_avb_read_slot_count(char *slot_count) 241 { 242 *slot_count = SLOT_NUM; 243 244 return 0; 245 } 246 247 int rk_avb_read_slot_suffixes(char *slot_suffixes) 248 { 249 memcpy(slot_suffixes, CURR_SYSTEM_SLOT_SUFFIX, 250 strlen(CURR_SYSTEM_SLOT_SUFFIX)); 251 252 return 0; 253 } 254 255 AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops, 256 unsigned int slot_number) 257 { 258 AvbABData ab_data, ab_data_orig; 259 unsigned int other_slot_number; 260 AvbIOResult ret; 261 262 avb_assert(slot_number < 2); 263 264 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); 265 if (ret != AVB_IO_RESULT_OK) { 266 goto out; 267 } 268 269 /* Make requested slot top priority, unsuccessful, and with max tries. */ 270 ab_data.slots[slot_number].priority = AVB_AB_MAX_PRIORITY; 271 ab_data.slots[slot_number].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; 272 ab_data.slots[slot_number].successful_boot = 0; 273 274 /* Ensure other slot doesn't have as high a priority. */ 275 other_slot_number = 1 - slot_number; 276 if (ab_data.slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) { 277 ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1; 278 } 279 280 ret = AVB_IO_RESULT_OK; 281 282 out: 283 if (ret == AVB_IO_RESULT_OK) { 284 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); 285 } 286 return ret; 287 } 288 289 int rk_avb_set_slot_active(unsigned int *slot_number) 290 { 291 AvbOps* ops; 292 ops = avb_ops_user_new(); 293 int ret = 0; 294 295 if (ops == NULL) { 296 printf("avb_ops_user_new() failed!\n"); 297 return -1; 298 } 299 300 debug("set_slot_active\n"); 301 if (avb_ab_mark_slot_active(ops->ab_ops, *slot_number) != 0) { 302 printf("set_slot_active error!\n"); 303 ret = -1; 304 } 305 306 avb_ops_user_free(ops); 307 return ret; 308 } 309 310 static bool slot_is_bootable(AvbABSlotData* slot) { 311 return (slot->priority > 0) && 312 (slot->successful_boot || (slot->tries_remaining > 0)); 313 } 314 315 AvbABFlowResult rk_avb_ab_slot_select(AvbABOps* ab_ops,char* select_slot) 316 { 317 AvbABFlowResult ret = AVB_AB_FLOW_RESULT_OK; 318 AvbIOResult io_ret = AVB_IO_RESULT_OK; 319 AvbABData ab_data; 320 size_t slot_index_to_boot; 321 static int last_slot_index = -1; 322 323 io_ret = ab_ops->read_ab_metadata(ab_ops, &ab_data); 324 if (io_ret != AVB_IO_RESULT_OK) { 325 printf("I/O error while loading A/B metadata.\n"); 326 ret = AVB_AB_FLOW_RESULT_ERROR_IO; 327 goto out; 328 } 329 if (slot_is_bootable(&ab_data.slots[0]) && slot_is_bootable(&ab_data.slots[1])) { 330 if (ab_data.slots[1].priority > ab_data.slots[0].priority) { 331 slot_index_to_boot = 1; 332 } else { 333 slot_index_to_boot = 0; 334 } 335 } else if(slot_is_bootable(&ab_data.slots[0])) { 336 slot_index_to_boot = 0; 337 } else if(slot_is_bootable(&ab_data.slots[1])) { 338 slot_index_to_boot = 1; 339 } else { 340 printf("No bootable slots found.\n"); 341 ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS; 342 goto out; 343 } 344 345 if (slot_index_to_boot == 0) { 346 strcpy(select_slot, "_a"); 347 } else if(slot_index_to_boot == 1) { 348 strcpy(select_slot, "_b"); 349 } 350 351 if (last_slot_index != slot_index_to_boot) { 352 last_slot_index = slot_index_to_boot; 353 printf("A/B-slot: %s, successful: %d, tries-remain: %d\n", 354 select_slot, 355 ab_data.slots[slot_index_to_boot].successful_boot, 356 ab_data.slots[slot_index_to_boot].tries_remaining); 357 } 358 out: 359 return ret; 360 } 361 362 AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops, 363 unsigned int slot_number) 364 { 365 AvbABData ab_data, ab_data_orig; 366 AvbIOResult ret; 367 368 avb_assert(slot_number < 2); 369 370 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); 371 if (ret != AVB_IO_RESULT_OK) { 372 goto out; 373 } 374 375 slot_set_unbootable(&ab_data.slots[slot_number]); 376 377 ret = AVB_IO_RESULT_OK; 378 379 out: 380 if (ret == AVB_IO_RESULT_OK) { 381 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); 382 } 383 return ret; 384 } 385 386 AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops, 387 unsigned int slot_number) 388 { 389 AvbABData ab_data, ab_data_orig; 390 AvbIOResult ret; 391 392 avb_assert(slot_number < 2); 393 394 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); 395 if (ret != AVB_IO_RESULT_OK) { 396 goto out; 397 } 398 399 if (!slot_is_bootable(&ab_data.slots[slot_number])) { 400 printf("Cannot mark unbootable slot as successful.\n"); 401 ret = AVB_IO_RESULT_OK; 402 goto out; 403 } 404 405 ab_data.slots[slot_number].tries_remaining = 0; 406 ab_data.slots[slot_number].successful_boot = 1; 407 408 ret = AVB_IO_RESULT_OK; 409 410 out: 411 if (ret == AVB_IO_RESULT_OK) { 412 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); 413 } 414 return ret; 415 } 416 417 int rk_get_lastboot(void) 418 { 419 420 AvbIOResult io_ret = AVB_IO_RESULT_OK; 421 AvbABData ab_data; 422 int lastboot = -1; 423 AvbOps* ops; 424 425 ops = avb_ops_user_new(); 426 if (ops == NULL) { 427 printf("avb_ops_user_new() failed!\n"); 428 return -1; 429 } 430 431 io_ret = ops->ab_ops->read_ab_metadata(ops->ab_ops, &ab_data); 432 if (io_ret != AVB_IO_RESULT_OK) { 433 printf("I/O error while loading A/B metadata.\n"); 434 goto out; 435 } 436 437 lastboot = ab_data.last_boot; 438 out: 439 avb_ops_user_free(ops); 440 441 return lastboot; 442 } 443 444 int rk_avb_get_current_slot(char *select_slot) 445 { 446 AvbOps* ops; 447 int ret = 0; 448 449 ops = avb_ops_user_new(); 450 if (ops == NULL) { 451 printf("avb_ops_user_new() failed!\n"); 452 return -1; 453 } 454 455 if (rk_avb_ab_slot_select(ops->ab_ops, select_slot) != 0) { 456 #ifndef CONFIG_ANDROID_AVB 457 printf("###There is no bootable slot, bring up last_boot!###\n"); 458 if (rk_get_lastboot() == 1) 459 memcpy(select_slot, "_b", 2); 460 else if(rk_get_lastboot() == 0) 461 memcpy(select_slot, "_a", 2); 462 else 463 #endif 464 return -1; 465 ret = 0; 466 } 467 468 avb_ops_user_free(ops); 469 return ret; 470 } 471 472 bool rk_avb_ab_have_bootable_slot(void) 473 { 474 char slot[3] = {0}; 475 476 if (rk_avb_get_current_slot(slot)) 477 return false; 478 else 479 return true; 480 } 481 482 int rk_avb_append_part_slot(const char *part_name, char *new_name) 483 { 484 char slot_suffix[3] = {0}; 485 486 if (!strcmp(part_name, "misc")) { 487 strcat(new_name, part_name); 488 return 0; 489 } 490 491 if (rk_avb_get_current_slot(slot_suffix)) { 492 printf("%s: failed to get slot suffix !\n", __func__); 493 return -1; 494 } 495 496 strcpy(new_name, part_name); 497 strcat(new_name, slot_suffix); 498 499 return 0; 500 } 501