xref: /rk3399_rockchip-uboot/lib/avb/libavb/avb_cmdline.c (revision 37a7bc39c0a3beca986e8c1c85d1dd6b9921e313)
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