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