1*37a7bc39SJason Zhu /* 2*37a7bc39SJason Zhu * Copyright (C) 2016 The Android Open Source Project 3*37a7bc39SJason Zhu * 4*37a7bc39SJason Zhu * Permission is hereby granted, free of charge, to any person 5*37a7bc39SJason Zhu * obtaining a copy of this software and associated documentation 6*37a7bc39SJason Zhu * files (the "Software"), to deal in the Software without 7*37a7bc39SJason Zhu * restriction, including without limitation the rights to use, copy, 8*37a7bc39SJason Zhu * modify, merge, publish, distribute, sublicense, and/or sell copies 9*37a7bc39SJason Zhu * of the Software, and to permit persons to whom the Software is 10*37a7bc39SJason Zhu * furnished to do so, subject to the following conditions: 11*37a7bc39SJason Zhu * 12*37a7bc39SJason Zhu * The above copyright notice and this permission notice shall be 13*37a7bc39SJason Zhu * included in all copies or substantial portions of the Software. 14*37a7bc39SJason Zhu * 15*37a7bc39SJason Zhu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16*37a7bc39SJason Zhu * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17*37a7bc39SJason Zhu * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18*37a7bc39SJason Zhu * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19*37a7bc39SJason Zhu * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20*37a7bc39SJason Zhu * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21*37a7bc39SJason Zhu * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22*37a7bc39SJason Zhu * SOFTWARE. 23*37a7bc39SJason Zhu */ 24*37a7bc39SJason Zhu 25*37a7bc39SJason Zhu #include <android_avb/avb_cmdline.h> 26*37a7bc39SJason Zhu #include <android_avb/avb_sha.h> 27*37a7bc39SJason Zhu #include <android_avb/avb_util.h> 28*37a7bc39SJason Zhu #include <android_avb/avb_version.h> 29*37a7bc39SJason Zhu 30*37a7bc39SJason Zhu #define NUM_GUIDS 3 31*37a7bc39SJason Zhu 32*37a7bc39SJason Zhu /* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with 33*37a7bc39SJason Zhu * values. Returns NULL on OOM, otherwise the cmdline with values 34*37a7bc39SJason Zhu * replaced. 35*37a7bc39SJason Zhu */ 36*37a7bc39SJason Zhu char* avb_sub_cmdline(AvbOps* ops, const char* cmdline, const char* ab_suffix, 37*37a7bc39SJason Zhu bool using_boot_for_vbmeta) { 38*37a7bc39SJason Zhu const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"}; 39*37a7bc39SJason Zhu const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)", 40*37a7bc39SJason Zhu "$(ANDROID_BOOT_PARTUUID)", 41*37a7bc39SJason Zhu "$(ANDROID_VBMETA_PARTUUID)"}; 42*37a7bc39SJason Zhu char* ret = NULL; 43*37a7bc39SJason Zhu AvbIOResult io_ret; 44*37a7bc39SJason Zhu size_t n; 45*37a7bc39SJason Zhu 46*37a7bc39SJason Zhu /* Special-case for when the top-level vbmeta struct is in the boot 47*37a7bc39SJason Zhu * partition. 48*37a7bc39SJason Zhu */ 49*37a7bc39SJason Zhu if (using_boot_for_vbmeta) { 50*37a7bc39SJason Zhu part_name_str[2] = "boot"; 51*37a7bc39SJason Zhu } 52*37a7bc39SJason Zhu 53*37a7bc39SJason Zhu /* Replace unique partition GUIDs */ 54*37a7bc39SJason Zhu for (n = 0; n < NUM_GUIDS; n++) { 55*37a7bc39SJason Zhu char part_name[AVB_PART_NAME_MAX_SIZE]; 56*37a7bc39SJason Zhu char guid_buf[37]; 57*37a7bc39SJason Zhu 58*37a7bc39SJason Zhu if (!avb_str_concat(part_name, 59*37a7bc39SJason Zhu sizeof part_name, 60*37a7bc39SJason Zhu part_name_str[n], 61*37a7bc39SJason Zhu avb_strlen(part_name_str[n]), 62*37a7bc39SJason Zhu ab_suffix, 63*37a7bc39SJason Zhu avb_strlen(ab_suffix))) { 64*37a7bc39SJason Zhu avb_error("Partition name and suffix does not fit.\n"); 65*37a7bc39SJason Zhu goto fail; 66*37a7bc39SJason Zhu } 67*37a7bc39SJason Zhu 68*37a7bc39SJason Zhu io_ret = ops->get_unique_guid_for_partition( 69*37a7bc39SJason Zhu ops, part_name, guid_buf, sizeof guid_buf); 70*37a7bc39SJason Zhu if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 71*37a7bc39SJason Zhu return NULL; 72*37a7bc39SJason Zhu } else if (io_ret != AVB_IO_RESULT_OK) { 73*37a7bc39SJason Zhu avb_error("Error getting unique GUID for partition.\n"); 74*37a7bc39SJason Zhu goto fail; 75*37a7bc39SJason Zhu } 76*37a7bc39SJason Zhu 77*37a7bc39SJason Zhu if (ret == NULL) { 78*37a7bc39SJason Zhu ret = avb_replace(cmdline, replace_str[n], guid_buf); 79*37a7bc39SJason Zhu } else { 80*37a7bc39SJason Zhu char* new_ret = avb_replace(ret, replace_str[n], guid_buf); 81*37a7bc39SJason Zhu avb_free(ret); 82*37a7bc39SJason Zhu ret = new_ret; 83*37a7bc39SJason Zhu } 84*37a7bc39SJason Zhu if (ret == NULL) { 85*37a7bc39SJason Zhu goto fail; 86*37a7bc39SJason Zhu } 87*37a7bc39SJason Zhu } 88*37a7bc39SJason Zhu 89*37a7bc39SJason Zhu return ret; 90*37a7bc39SJason Zhu 91*37a7bc39SJason Zhu fail: 92*37a7bc39SJason Zhu if (ret != NULL) { 93*37a7bc39SJason Zhu avb_free(ret); 94*37a7bc39SJason Zhu } 95*37a7bc39SJason Zhu return NULL; 96*37a7bc39SJason Zhu } 97*37a7bc39SJason Zhu 98*37a7bc39SJason Zhu static int cmdline_append_option(AvbSlotVerifyData* slot_data, 99*37a7bc39SJason Zhu const char* key, 100*37a7bc39SJason Zhu const char* value) { 101*37a7bc39SJason Zhu size_t offset, key_len, value_len; 102*37a7bc39SJason Zhu char* new_cmdline; 103*37a7bc39SJason Zhu 104*37a7bc39SJason Zhu key_len = avb_strlen(key); 105*37a7bc39SJason Zhu value_len = avb_strlen(value); 106*37a7bc39SJason Zhu 107*37a7bc39SJason Zhu offset = 0; 108*37a7bc39SJason Zhu if (slot_data->cmdline != NULL) { 109*37a7bc39SJason Zhu offset = avb_strlen(slot_data->cmdline); 110*37a7bc39SJason Zhu if (offset > 0) { 111*37a7bc39SJason Zhu offset += 1; 112*37a7bc39SJason Zhu } 113*37a7bc39SJason Zhu } 114*37a7bc39SJason Zhu 115*37a7bc39SJason Zhu new_cmdline = avb_calloc(offset + key_len + value_len + 2); 116*37a7bc39SJason Zhu if (new_cmdline == NULL) { 117*37a7bc39SJason Zhu return 0; 118*37a7bc39SJason Zhu } 119*37a7bc39SJason Zhu if (offset > 0) { 120*37a7bc39SJason Zhu avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1); 121*37a7bc39SJason Zhu new_cmdline[offset - 1] = ' '; 122*37a7bc39SJason Zhu } 123*37a7bc39SJason Zhu avb_memcpy(new_cmdline + offset, key, key_len); 124*37a7bc39SJason Zhu new_cmdline[offset + key_len] = '='; 125*37a7bc39SJason Zhu avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len); 126*37a7bc39SJason Zhu if (slot_data->cmdline != NULL) { 127*37a7bc39SJason Zhu avb_free(slot_data->cmdline); 128*37a7bc39SJason Zhu } 129*37a7bc39SJason Zhu slot_data->cmdline = new_cmdline; 130*37a7bc39SJason Zhu 131*37a7bc39SJason Zhu return 1; 132*37a7bc39SJason Zhu } 133*37a7bc39SJason Zhu 134*37a7bc39SJason Zhu #define AVB_MAX_DIGITS_UINT64 32 135*37a7bc39SJason Zhu 136*37a7bc39SJason Zhu /* Writes |value| to |digits| in base 10 followed by a NUL byte. 137*37a7bc39SJason Zhu * Returns number of characters written excluding the NUL byte. 138*37a7bc39SJason Zhu */ 139*37a7bc39SJason Zhu static size_t uint64_to_base10(uint64_t value, 140*37a7bc39SJason Zhu char digits[AVB_MAX_DIGITS_UINT64]) { 141*37a7bc39SJason Zhu char rev_digits[AVB_MAX_DIGITS_UINT64]; 142*37a7bc39SJason Zhu size_t n, num_digits; 143*37a7bc39SJason Zhu 144*37a7bc39SJason Zhu for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) { 145*37a7bc39SJason Zhu rev_digits[num_digits++] = avb_div_by_10(&value) + '0'; 146*37a7bc39SJason Zhu if (value == 0) { 147*37a7bc39SJason Zhu break; 148*37a7bc39SJason Zhu } 149*37a7bc39SJason Zhu } 150*37a7bc39SJason Zhu 151*37a7bc39SJason Zhu for (n = 0; n < num_digits; n++) { 152*37a7bc39SJason Zhu digits[n] = rev_digits[num_digits - 1 - n]; 153*37a7bc39SJason Zhu } 154*37a7bc39SJason Zhu digits[n] = '\0'; 155*37a7bc39SJason Zhu return n; 156*37a7bc39SJason Zhu } 157*37a7bc39SJason Zhu 158*37a7bc39SJason Zhu static int cmdline_append_version(AvbSlotVerifyData* slot_data, 159*37a7bc39SJason Zhu const char* key, 160*37a7bc39SJason Zhu uint64_t major_version, 161*37a7bc39SJason Zhu uint64_t minor_version) { 162*37a7bc39SJason Zhu char major_digits[AVB_MAX_DIGITS_UINT64]; 163*37a7bc39SJason Zhu char minor_digits[AVB_MAX_DIGITS_UINT64]; 164*37a7bc39SJason Zhu char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1]; 165*37a7bc39SJason Zhu size_t num_major_digits, num_minor_digits; 166*37a7bc39SJason Zhu 167*37a7bc39SJason Zhu num_major_digits = uint64_to_base10(major_version, major_digits); 168*37a7bc39SJason Zhu num_minor_digits = uint64_to_base10(minor_version, minor_digits); 169*37a7bc39SJason Zhu avb_memcpy(combined, major_digits, num_major_digits); 170*37a7bc39SJason Zhu combined[num_major_digits] = '.'; 171*37a7bc39SJason Zhu avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits); 172*37a7bc39SJason Zhu combined[num_major_digits + 1 + num_minor_digits] = '\0'; 173*37a7bc39SJason Zhu 174*37a7bc39SJason Zhu return cmdline_append_option(slot_data, key, combined); 175*37a7bc39SJason Zhu } 176*37a7bc39SJason Zhu 177*37a7bc39SJason Zhu static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data, 178*37a7bc39SJason Zhu const char* key, 179*37a7bc39SJason Zhu uint64_t value) { 180*37a7bc39SJason Zhu char digits[AVB_MAX_DIGITS_UINT64]; 181*37a7bc39SJason Zhu uint64_to_base10(value, digits); 182*37a7bc39SJason Zhu return cmdline_append_option(slot_data, key, digits); 183*37a7bc39SJason Zhu } 184*37a7bc39SJason Zhu 185*37a7bc39SJason Zhu static int cmdline_append_hex(AvbSlotVerifyData* slot_data, 186*37a7bc39SJason Zhu const char* key, 187*37a7bc39SJason Zhu const uint8_t* data, 188*37a7bc39SJason Zhu size_t data_len) { 189*37a7bc39SJason Zhu char hex_digits[17] = "0123456789abcdef"; 190*37a7bc39SJason Zhu char* hex_data; 191*37a7bc39SJason Zhu int ret; 192*37a7bc39SJason Zhu size_t n; 193*37a7bc39SJason Zhu 194*37a7bc39SJason Zhu hex_data = avb_malloc(data_len * 2 + 1); 195*37a7bc39SJason Zhu if (hex_data == NULL) { 196*37a7bc39SJason Zhu return 0; 197*37a7bc39SJason Zhu } 198*37a7bc39SJason Zhu 199*37a7bc39SJason Zhu for (n = 0; n < data_len; n++) { 200*37a7bc39SJason Zhu hex_data[n * 2] = hex_digits[data[n] >> 4]; 201*37a7bc39SJason Zhu hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f]; 202*37a7bc39SJason Zhu } 203*37a7bc39SJason Zhu hex_data[n * 2] = '\0'; 204*37a7bc39SJason Zhu 205*37a7bc39SJason Zhu ret = cmdline_append_option(slot_data, key, hex_data); 206*37a7bc39SJason Zhu avb_free(hex_data); 207*37a7bc39SJason Zhu return ret; 208*37a7bc39SJason Zhu } 209*37a7bc39SJason Zhu 210*37a7bc39SJason Zhu AvbSlotVerifyResult avb_append_options( 211*37a7bc39SJason Zhu AvbOps* ops, 212*37a7bc39SJason Zhu AvbSlotVerifyData* slot_data, 213*37a7bc39SJason Zhu AvbVBMetaImageHeader* toplevel_vbmeta, 214*37a7bc39SJason Zhu AvbAlgorithmType algorithm_type, 215*37a7bc39SJason Zhu AvbHashtreeErrorMode hashtree_error_mode) { 216*37a7bc39SJason Zhu AvbSlotVerifyResult ret; 217*37a7bc39SJason Zhu const char* verity_mode = NULL; 218*37a7bc39SJason Zhu bool is_device_unlocked; 219*37a7bc39SJason Zhu AvbIOResult io_ret; 220*37a7bc39SJason Zhu 221*37a7bc39SJason Zhu /* Add androidboot.vbmeta.device option. */ 222*37a7bc39SJason Zhu if (!cmdline_append_option(slot_data, 223*37a7bc39SJason Zhu "androidboot.vbmeta.device", 224*37a7bc39SJason Zhu "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) { 225*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 226*37a7bc39SJason Zhu goto out; 227*37a7bc39SJason Zhu } 228*37a7bc39SJason Zhu 229*37a7bc39SJason Zhu /* Add androidboot.vbmeta.avb_version option. */ 230*37a7bc39SJason Zhu if (!cmdline_append_version(slot_data, 231*37a7bc39SJason Zhu "androidboot.vbmeta.avb_version", 232*37a7bc39SJason Zhu AVB_VERSION_MAJOR, 233*37a7bc39SJason Zhu AVB_VERSION_MINOR)) { 234*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 235*37a7bc39SJason Zhu goto out; 236*37a7bc39SJason Zhu } 237*37a7bc39SJason Zhu 238*37a7bc39SJason Zhu /* Set androidboot.avb.device_state to "locked" or "unlocked". */ 239*37a7bc39SJason Zhu io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked); 240*37a7bc39SJason Zhu if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 241*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 242*37a7bc39SJason Zhu goto out; 243*37a7bc39SJason Zhu } else if (io_ret != AVB_IO_RESULT_OK) { 244*37a7bc39SJason Zhu avb_error("Error getting device state.\n"); 245*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; 246*37a7bc39SJason Zhu goto out; 247*37a7bc39SJason Zhu } 248*37a7bc39SJason Zhu if (!cmdline_append_option(slot_data, 249*37a7bc39SJason Zhu "androidboot.vbmeta.device_state", 250*37a7bc39SJason Zhu is_device_unlocked ? "unlocked" : "locked")) { 251*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 252*37a7bc39SJason Zhu goto out; 253*37a7bc39SJason Zhu } 254*37a7bc39SJason Zhu 255*37a7bc39SJason Zhu /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash 256*37a7bc39SJason Zhu * function as is used to sign vbmeta. 257*37a7bc39SJason Zhu */ 258*37a7bc39SJason Zhu switch (algorithm_type) { 259*37a7bc39SJason Zhu /* Explicit fallthrough. */ 260*37a7bc39SJason Zhu case AVB_ALGORITHM_TYPE_NONE: 261*37a7bc39SJason Zhu case AVB_ALGORITHM_TYPE_SHA256_RSA2048: 262*37a7bc39SJason Zhu case AVB_ALGORITHM_TYPE_SHA256_RSA4096: 263*37a7bc39SJason Zhu case AVB_ALGORITHM_TYPE_SHA256_RSA8192: { 264*37a7bc39SJason Zhu AvbSHA256Ctx ctx; 265*37a7bc39SJason Zhu size_t n, total_size = 0; 266*37a7bc39SJason Zhu avb_sha256_init(&ctx); 267*37a7bc39SJason Zhu for (n = 0; n < slot_data->num_vbmeta_images; n++) { 268*37a7bc39SJason Zhu avb_sha256_update(&ctx, 269*37a7bc39SJason Zhu slot_data->vbmeta_images[n].vbmeta_data, 270*37a7bc39SJason Zhu slot_data->vbmeta_images[n].vbmeta_size); 271*37a7bc39SJason Zhu total_size += slot_data->vbmeta_images[n].vbmeta_size; 272*37a7bc39SJason Zhu } 273*37a7bc39SJason Zhu if (!cmdline_append_option( 274*37a7bc39SJason Zhu slot_data, "androidboot.vbmeta.hash_alg", "sha256") || 275*37a7bc39SJason Zhu !cmdline_append_uint64_base10( 276*37a7bc39SJason Zhu slot_data, "androidboot.vbmeta.size", total_size) || 277*37a7bc39SJason Zhu !cmdline_append_hex(slot_data, 278*37a7bc39SJason Zhu "androidboot.vbmeta.digest", 279*37a7bc39SJason Zhu avb_sha256_final(&ctx), 280*37a7bc39SJason Zhu AVB_SHA256_DIGEST_SIZE)) { 281*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 282*37a7bc39SJason Zhu goto out; 283*37a7bc39SJason Zhu } 284*37a7bc39SJason Zhu } break; 285*37a7bc39SJason Zhu /* Explicit fallthrough. */ 286*37a7bc39SJason Zhu case AVB_ALGORITHM_TYPE_SHA512_RSA2048: 287*37a7bc39SJason Zhu case AVB_ALGORITHM_TYPE_SHA512_RSA4096: 288*37a7bc39SJason Zhu case AVB_ALGORITHM_TYPE_SHA512_RSA8192: { 289*37a7bc39SJason Zhu AvbSHA512Ctx ctx; 290*37a7bc39SJason Zhu size_t n, total_size = 0; 291*37a7bc39SJason Zhu avb_sha512_init(&ctx); 292*37a7bc39SJason Zhu for (n = 0; n < slot_data->num_vbmeta_images; n++) { 293*37a7bc39SJason Zhu avb_sha512_update(&ctx, 294*37a7bc39SJason Zhu slot_data->vbmeta_images[n].vbmeta_data, 295*37a7bc39SJason Zhu slot_data->vbmeta_images[n].vbmeta_size); 296*37a7bc39SJason Zhu total_size += slot_data->vbmeta_images[n].vbmeta_size; 297*37a7bc39SJason Zhu } 298*37a7bc39SJason Zhu if (!cmdline_append_option( 299*37a7bc39SJason Zhu slot_data, "androidboot.vbmeta.hash_alg", "sha512") || 300*37a7bc39SJason Zhu !cmdline_append_uint64_base10( 301*37a7bc39SJason Zhu slot_data, "androidboot.vbmeta.size", total_size) || 302*37a7bc39SJason Zhu !cmdline_append_hex(slot_data, 303*37a7bc39SJason Zhu "androidboot.vbmeta.digest", 304*37a7bc39SJason Zhu avb_sha512_final(&ctx), 305*37a7bc39SJason Zhu AVB_SHA512_DIGEST_SIZE)) { 306*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 307*37a7bc39SJason Zhu goto out; 308*37a7bc39SJason Zhu } 309*37a7bc39SJason Zhu } break; 310*37a7bc39SJason Zhu case _AVB_ALGORITHM_NUM_TYPES: 311*37a7bc39SJason Zhu avb_assert_not_reached(); 312*37a7bc39SJason Zhu break; 313*37a7bc39SJason Zhu } 314*37a7bc39SJason Zhu 315*37a7bc39SJason Zhu /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */ 316*37a7bc39SJason Zhu if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) { 317*37a7bc39SJason Zhu verity_mode = "disabled"; 318*37a7bc39SJason Zhu } else { 319*37a7bc39SJason Zhu const char* dm_verity_mode = NULL; 320*37a7bc39SJason Zhu char* new_ret; 321*37a7bc39SJason Zhu 322*37a7bc39SJason Zhu switch (hashtree_error_mode) { 323*37a7bc39SJason Zhu case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE: 324*37a7bc39SJason Zhu if (!cmdline_append_option( 325*37a7bc39SJason Zhu slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) { 326*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 327*37a7bc39SJason Zhu goto out; 328*37a7bc39SJason Zhu } 329*37a7bc39SJason Zhu verity_mode = "enforcing"; 330*37a7bc39SJason Zhu dm_verity_mode = "restart_on_corruption"; 331*37a7bc39SJason Zhu break; 332*37a7bc39SJason Zhu case AVB_HASHTREE_ERROR_MODE_RESTART: 333*37a7bc39SJason Zhu verity_mode = "enforcing"; 334*37a7bc39SJason Zhu dm_verity_mode = "restart_on_corruption"; 335*37a7bc39SJason Zhu break; 336*37a7bc39SJason Zhu case AVB_HASHTREE_ERROR_MODE_EIO: 337*37a7bc39SJason Zhu verity_mode = "eio"; 338*37a7bc39SJason Zhu /* For now there's no option to specify the EIO mode. So 339*37a7bc39SJason Zhu * just use 'ignore_zero_blocks' since that's already set 340*37a7bc39SJason Zhu * and dm-verity-target.c supports specifying this multiple 341*37a7bc39SJason Zhu * times. 342*37a7bc39SJason Zhu */ 343*37a7bc39SJason Zhu dm_verity_mode = "ignore_zero_blocks"; 344*37a7bc39SJason Zhu break; 345*37a7bc39SJason Zhu case AVB_HASHTREE_ERROR_MODE_LOGGING: 346*37a7bc39SJason Zhu verity_mode = "logging"; 347*37a7bc39SJason Zhu dm_verity_mode = "ignore_corruption"; 348*37a7bc39SJason Zhu break; 349*37a7bc39SJason Zhu } 350*37a7bc39SJason Zhu new_ret = avb_replace( 351*37a7bc39SJason Zhu slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode); 352*37a7bc39SJason Zhu avb_free(slot_data->cmdline); 353*37a7bc39SJason Zhu slot_data->cmdline = new_ret; 354*37a7bc39SJason Zhu if (slot_data->cmdline == NULL) { 355*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 356*37a7bc39SJason Zhu goto out; 357*37a7bc39SJason Zhu } 358*37a7bc39SJason Zhu } 359*37a7bc39SJason Zhu if (!cmdline_append_option( 360*37a7bc39SJason Zhu slot_data, "androidboot.veritymode", verity_mode)) { 361*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 362*37a7bc39SJason Zhu goto out; 363*37a7bc39SJason Zhu } 364*37a7bc39SJason Zhu 365*37a7bc39SJason Zhu ret = AVB_SLOT_VERIFY_RESULT_OK; 366*37a7bc39SJason Zhu 367*37a7bc39SJason Zhu out: 368*37a7bc39SJason Zhu 369*37a7bc39SJason Zhu return ret; 370*37a7bc39SJason Zhu } 371*37a7bc39SJason Zhu 372