1*37a7bc39SJason Zhu /* 2*37a7bc39SJason Zhu * Copyright (C) 2017 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 <common.h> 26*37a7bc39SJason Zhu #include <image.h> 27*37a7bc39SJason Zhu #include <android_image.h> 28*37a7bc39SJason Zhu #include <malloc.h> 29*37a7bc39SJason Zhu #include <mapmem.h> 30*37a7bc39SJason Zhu #include <errno.h> 31*37a7bc39SJason Zhu #include <command.h> 32*37a7bc39SJason Zhu #include <mmc.h> 33*37a7bc39SJason Zhu #include <blk.h> 34*37a7bc39SJason Zhu #include <part.h> 35*37a7bc39SJason Zhu #include <android_avb/avb_ops_user.h> 36*37a7bc39SJason Zhu #include <android_avb/libavb_ab.h> 37*37a7bc39SJason Zhu #include <android_avb/avb_atx_validate.h> 38*37a7bc39SJason Zhu #include <android_avb/avb_atx_types.h> 39*37a7bc39SJason Zhu #include <optee_include/OpteeClientInterface.h> 40*37a7bc39SJason Zhu #include <optee_include/tee_api_defines.h> 41*37a7bc39SJason Zhu #include <android_avb/avb_vbmeta_image.h> 42*37a7bc39SJason Zhu #include <android_avb/avb_atx_validate.h> 43*37a7bc39SJason Zhu 44*37a7bc39SJason Zhu static void byte_to_block(int64_t *offset, 45*37a7bc39SJason Zhu size_t *num_bytes, 46*37a7bc39SJason Zhu lbaint_t *offset_blk, 47*37a7bc39SJason Zhu lbaint_t *blkcnt) 48*37a7bc39SJason Zhu { 49*37a7bc39SJason Zhu *offset_blk = (lbaint_t)(*offset / 512); 50*37a7bc39SJason Zhu if (*num_bytes % 512 == 0) { 51*37a7bc39SJason Zhu if (*offset % 512 == 0) { 52*37a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512); 53*37a7bc39SJason Zhu } else { 54*37a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512) + 1; 55*37a7bc39SJason Zhu } 56*37a7bc39SJason Zhu } else { 57*37a7bc39SJason Zhu if (*offset % 512 == 0) { 58*37a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512) + 1; 59*37a7bc39SJason Zhu } else { 60*37a7bc39SJason Zhu if ((*offset % 512) + (*num_bytes % 512) < 512 || 61*37a7bc39SJason Zhu (*offset % 512) + (*num_bytes % 512) == 512) { 62*37a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512) + 1; 63*37a7bc39SJason Zhu } else { 64*37a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512) + 2; 65*37a7bc39SJason Zhu } 66*37a7bc39SJason Zhu } 67*37a7bc39SJason Zhu } 68*37a7bc39SJason Zhu } 69*37a7bc39SJason Zhu 70*37a7bc39SJason Zhu static AvbIOResult read_from_partition(AvbOps* ops, 71*37a7bc39SJason Zhu const char* partition, 72*37a7bc39SJason Zhu int64_t offset, 73*37a7bc39SJason Zhu size_t num_bytes, 74*37a7bc39SJason Zhu void* buffer, 75*37a7bc39SJason Zhu size_t* out_num_read) 76*37a7bc39SJason Zhu { 77*37a7bc39SJason Zhu char *dev_iface = "mmc"; 78*37a7bc39SJason Zhu int dev_num = 0; 79*37a7bc39SJason Zhu struct blk_desc *dev_desc; 80*37a7bc39SJason Zhu lbaint_t offset_blk, blkcnt; 81*37a7bc39SJason Zhu disk_partition_t part_info; 82*37a7bc39SJason Zhu 83*37a7bc39SJason Zhu byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt); 84*37a7bc39SJason Zhu dev_desc = blk_get_dev(dev_iface, dev_num); 85*37a7bc39SJason Zhu if (!dev_desc) { 86*37a7bc39SJason Zhu printf("Could not find %s %d\n", dev_iface, dev_num); 87*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 88*37a7bc39SJason Zhu } 89*37a7bc39SJason Zhu 90*37a7bc39SJason Zhu if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) { 91*37a7bc39SJason Zhu printf("Could not find \"%s\" partition\n", partition); 92*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 93*37a7bc39SJason Zhu } 94*37a7bc39SJason Zhu 95*37a7bc39SJason Zhu if((offset % 512 == 0) && (num_bytes % 512 == 0)) { 96*37a7bc39SJason Zhu blk_dread(dev_desc, part_info.start + offset_blk, blkcnt, buffer); 97*37a7bc39SJason Zhu *out_num_read = blkcnt * 512; 98*37a7bc39SJason Zhu } else { 99*37a7bc39SJason Zhu char *buffer_temp; 100*37a7bc39SJason Zhu buffer_temp = malloc(512 * blkcnt); 101*37a7bc39SJason Zhu if (buffer_temp == NULL) { 102*37a7bc39SJason Zhu printf("malloc error!\n"); 103*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_OOM; 104*37a7bc39SJason Zhu } 105*37a7bc39SJason Zhu blk_dread(dev_desc, part_info.start + offset_blk, blkcnt, buffer_temp); 106*37a7bc39SJason Zhu memcpy(buffer, buffer_temp + (offset % 512), num_bytes); 107*37a7bc39SJason Zhu *out_num_read = num_bytes; 108*37a7bc39SJason Zhu free(buffer_temp); 109*37a7bc39SJason Zhu } 110*37a7bc39SJason Zhu 111*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 112*37a7bc39SJason Zhu } 113*37a7bc39SJason Zhu 114*37a7bc39SJason Zhu static AvbIOResult write_to_partition(AvbOps* ops, 115*37a7bc39SJason Zhu const char* partition, 116*37a7bc39SJason Zhu int64_t offset, 117*37a7bc39SJason Zhu size_t num_bytes, 118*37a7bc39SJason Zhu const void* buffer) 119*37a7bc39SJason Zhu { 120*37a7bc39SJason Zhu const char *dev_iface = "mmc"; 121*37a7bc39SJason Zhu int dev_num = 0; 122*37a7bc39SJason Zhu struct blk_desc *dev_desc; 123*37a7bc39SJason Zhu char *buffer_temp; 124*37a7bc39SJason Zhu disk_partition_t part_info; 125*37a7bc39SJason Zhu lbaint_t offset_blk, blkcnt; 126*37a7bc39SJason Zhu 127*37a7bc39SJason Zhu byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt); 128*37a7bc39SJason Zhu buffer_temp = malloc(512 * blkcnt); 129*37a7bc39SJason Zhu if (buffer_temp == NULL) { 130*37a7bc39SJason Zhu printf("malloc error!\n"); 131*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_OOM; 132*37a7bc39SJason Zhu } 133*37a7bc39SJason Zhu memset(buffer_temp, 0, 512 * blkcnt); 134*37a7bc39SJason Zhu dev_desc = blk_get_dev(dev_iface, dev_num); 135*37a7bc39SJason Zhu if (!dev_desc) { 136*37a7bc39SJason Zhu printf("Could not find %s %d\n", dev_iface, dev_num); 137*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 138*37a7bc39SJason Zhu } 139*37a7bc39SJason Zhu 140*37a7bc39SJason Zhu if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) { 141*37a7bc39SJason Zhu printf("Could not find \"%s\" partition\n", partition); 142*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 143*37a7bc39SJason Zhu } 144*37a7bc39SJason Zhu 145*37a7bc39SJason Zhu if ((offset % 512 != 0) && (num_bytes % 512) != 0) { 146*37a7bc39SJason Zhu blk_dread(dev_desc, part_info.start + offset_blk, blkcnt, buffer_temp); 147*37a7bc39SJason Zhu } 148*37a7bc39SJason Zhu 149*37a7bc39SJason Zhu memcpy(buffer_temp, buffer + (offset % 512), num_bytes); 150*37a7bc39SJason Zhu blk_dwrite(dev_desc, part_info.start + offset_blk, blkcnt, buffer); 151*37a7bc39SJason Zhu free(buffer_temp); 152*37a7bc39SJason Zhu 153*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 154*37a7bc39SJason Zhu } 155*37a7bc39SJason Zhu 156*37a7bc39SJason Zhu static AvbIOResult validate_vbmeta_public_key( 157*37a7bc39SJason Zhu AvbOps *ops, 158*37a7bc39SJason Zhu const uint8_t *public_key_data, 159*37a7bc39SJason Zhu size_t public_key_length, 160*37a7bc39SJason Zhu const uint8_t *public_key_metadata, 161*37a7bc39SJason Zhu size_t public_key_metadata_length, 162*37a7bc39SJason Zhu bool *out_is_trusted) 163*37a7bc39SJason Zhu { 164*37a7bc39SJason Zhu #ifdef AVB_VBMETA_PUBLIC_KEY_VALIDATE 165*37a7bc39SJason Zhu if (out_is_trusted != NULL) { 166*37a7bc39SJason Zhu avb_atx_validate_vbmeta_public_key(ops, 167*37a7bc39SJason Zhu public_key_data, 168*37a7bc39SJason Zhu public_key_length, 169*37a7bc39SJason Zhu public_key_metadata, 170*37a7bc39SJason Zhu public_key_metadata_length, 171*37a7bc39SJason Zhu out_is_trusted); 172*37a7bc39SJason Zhu } 173*37a7bc39SJason Zhu #else 174*37a7bc39SJason Zhu if (out_is_trusted != NULL) { 175*37a7bc39SJason Zhu *out_is_trusted = true; 176*37a7bc39SJason Zhu } 177*37a7bc39SJason Zhu #endif 178*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 179*37a7bc39SJason Zhu } 180*37a7bc39SJason Zhu 181*37a7bc39SJason Zhu static AvbIOResult read_rollback_index(AvbOps *ops, 182*37a7bc39SJason Zhu size_t rollback_index_location, 183*37a7bc39SJason Zhu uint64_t *out_rollback_index) 184*37a7bc39SJason Zhu { 185*37a7bc39SJason Zhu if (out_rollback_index != NULL) { 186*37a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 187*37a7bc39SJason Zhu int ret; 188*37a7bc39SJason Zhu ret = trusty_read_rollback_index(rollback_index_location, 189*37a7bc39SJason Zhu out_rollback_index); 190*37a7bc39SJason Zhu if (ret == TEE_ERROR_GENERIC) { 191*37a7bc39SJason Zhu *out_rollback_index = 0; 192*37a7bc39SJason Zhu ret = trusty_write_rollback_index(rollback_index_location, 193*37a7bc39SJason Zhu *out_rollback_index); 194*37a7bc39SJason Zhu if (ret != 0) { 195*37a7bc39SJason Zhu printf("%s: init rollback index error\n", __FILE__); 196*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 197*37a7bc39SJason Zhu } 198*37a7bc39SJason Zhu ret = trusty_read_rollback_index(rollback_index_location, 199*37a7bc39SJason Zhu out_rollback_index); 200*37a7bc39SJason Zhu if (ret == 0) 201*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 202*37a7bc39SJason Zhu } else if (ret == 0) { 203*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 204*37a7bc39SJason Zhu } else { 205*37a7bc39SJason Zhu printf("trusty_read_rollback_index ret = %x\n", ret); 206*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 207*37a7bc39SJason Zhu } 208*37a7bc39SJason Zhu #endif 209*37a7bc39SJason Zhu } 210*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 211*37a7bc39SJason Zhu } 212*37a7bc39SJason Zhu 213*37a7bc39SJason Zhu static AvbIOResult write_rollback_index(AvbOps *ops, 214*37a7bc39SJason Zhu size_t rollback_index_location, 215*37a7bc39SJason Zhu uint64_t rollback_index) 216*37a7bc39SJason Zhu { 217*37a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 218*37a7bc39SJason Zhu if (trusty_write_rollback_index(rollback_index_location, rollback_index)) { 219*37a7bc39SJason Zhu printf("%s: Fail to write rollback index\n", __FILE__); 220*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 221*37a7bc39SJason Zhu } 222*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 223*37a7bc39SJason Zhu #endif 224*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 225*37a7bc39SJason Zhu } 226*37a7bc39SJason Zhu 227*37a7bc39SJason Zhu static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked) 228*37a7bc39SJason Zhu { 229*37a7bc39SJason Zhu if (out_is_unlocked != NULL) { 230*37a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 231*37a7bc39SJason Zhu int ret; 232*37a7bc39SJason Zhu 233*37a7bc39SJason Zhu ret = trusty_read_lock_state((uint8_t *)out_is_unlocked); 234*37a7bc39SJason Zhu if (ret == TEE_ERROR_GENERIC) { 235*37a7bc39SJason Zhu *out_is_unlocked = 1; 236*37a7bc39SJason Zhu if (trusty_write_lock_state(*out_is_unlocked)) { 237*37a7bc39SJason Zhu printf("%s: init lock state error\n", __FILE__); 238*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 239*37a7bc39SJason Zhu } 240*37a7bc39SJason Zhu 241*37a7bc39SJason Zhu ret = trusty_read_lock_state((uint8_t *)out_is_unlocked); 242*37a7bc39SJason Zhu if(ret == 0) 243*37a7bc39SJason Zhu return 0; 244*37a7bc39SJason Zhu } else if (ret == 0) { 245*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 246*37a7bc39SJason Zhu } else { 247*37a7bc39SJason Zhu printf("read_is_device_unlocked ret = %x\n", ret); 248*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 249*37a7bc39SJason Zhu } 250*37a7bc39SJason Zhu #endif 251*37a7bc39SJason Zhu } 252*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 253*37a7bc39SJason Zhu } 254*37a7bc39SJason Zhu 255*37a7bc39SJason Zhu static AvbIOResult write_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked) 256*37a7bc39SJason Zhu { 257*37a7bc39SJason Zhu if (out_is_unlocked != NULL) { 258*37a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 259*37a7bc39SJason Zhu if (trusty_write_lock_state(*out_is_unlocked)) { 260*37a7bc39SJason Zhu printf("%s: Fail to write lock state\n", __FILE__); 261*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 262*37a7bc39SJason Zhu } 263*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 264*37a7bc39SJason Zhu #endif 265*37a7bc39SJason Zhu } 266*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 267*37a7bc39SJason Zhu } 268*37a7bc39SJason Zhu 269*37a7bc39SJason Zhu static AvbIOResult get_size_of_partition(AvbOps *ops, 270*37a7bc39SJason Zhu const char *partition, 271*37a7bc39SJason Zhu uint64_t *out_size_in_bytes) 272*37a7bc39SJason Zhu { 273*37a7bc39SJason Zhu const char *dev_iface = "mmc"; 274*37a7bc39SJason Zhu int dev_num = 0; 275*37a7bc39SJason Zhu struct blk_desc *dev_desc; 276*37a7bc39SJason Zhu disk_partition_t part_info; 277*37a7bc39SJason Zhu 278*37a7bc39SJason Zhu dev_desc = blk_get_dev(dev_iface, dev_num); 279*37a7bc39SJason Zhu if (!dev_desc) { 280*37a7bc39SJason Zhu printf("Could not find %s %d\n", dev_iface, dev_num); 281*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 282*37a7bc39SJason Zhu } 283*37a7bc39SJason Zhu 284*37a7bc39SJason Zhu if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) { 285*37a7bc39SJason Zhu printf("Could not find \"%s\" partition\n", partition); 286*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 287*37a7bc39SJason Zhu } 288*37a7bc39SJason Zhu *out_size_in_bytes = (part_info.size) * 512; 289*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 290*37a7bc39SJason Zhu } 291*37a7bc39SJason Zhu 292*37a7bc39SJason Zhu static AvbIOResult get_unique_guid_for_partition(AvbOps *ops, 293*37a7bc39SJason Zhu const char *partition, 294*37a7bc39SJason Zhu char *guid_buf, 295*37a7bc39SJason Zhu size_t guid_buf_size) 296*37a7bc39SJason Zhu { 297*37a7bc39SJason Zhu const char *dev_iface = "mmc"; 298*37a7bc39SJason Zhu int dev_num = 0; 299*37a7bc39SJason Zhu struct blk_desc *dev_desc; 300*37a7bc39SJason Zhu disk_partition_t part_info; 301*37a7bc39SJason Zhu dev_desc = blk_get_dev(dev_iface, dev_num); 302*37a7bc39SJason Zhu if (!dev_desc) { 303*37a7bc39SJason Zhu printf("Could not find %s %d\n", dev_iface, dev_num); 304*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 305*37a7bc39SJason Zhu } 306*37a7bc39SJason Zhu 307*37a7bc39SJason Zhu if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) { 308*37a7bc39SJason Zhu printf("Could not find \"%s\" partition\n", partition); 309*37a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 310*37a7bc39SJason Zhu } 311*37a7bc39SJason Zhu if (guid_buf != NULL && guid_buf_size > 0) { 312*37a7bc39SJason Zhu memcpy(guid_buf, part_info.uuid, guid_buf_size); 313*37a7bc39SJason Zhu } 314*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 315*37a7bc39SJason Zhu } 316*37a7bc39SJason Zhu 317*37a7bc39SJason Zhu /* read permanent attributes from rpmb */ 318*37a7bc39SJason Zhu AvbIOResult avb_read_perm_attr(AvbAtxOps* atx_ops, 319*37a7bc39SJason Zhu AvbAtxPermanentAttributes* attributes) 320*37a7bc39SJason Zhu { 321*37a7bc39SJason Zhu if (attributes != NULL) { 322*37a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 323*37a7bc39SJason Zhu trusty_read_permanent_attributes((uint8_t *)attributes, 324*37a7bc39SJason Zhu sizeof(struct AvbAtxPermanentAttributes)); 325*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 326*37a7bc39SJason Zhu #endif 327*37a7bc39SJason Zhu } 328*37a7bc39SJason Zhu 329*37a7bc39SJason Zhu return -1; 330*37a7bc39SJason Zhu } 331*37a7bc39SJason Zhu 332*37a7bc39SJason Zhu /*read permanent attributes hash from efuse */ 333*37a7bc39SJason Zhu AvbIOResult avb_read_perm_attr_hash(AvbAtxOps* atx_ops, 334*37a7bc39SJason Zhu uint8_t hash[AVB_SHA256_DIGEST_SIZE]) 335*37a7bc39SJason Zhu { 336*37a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 337*37a7bc39SJason Zhu if (trusty_read_attribute_hash((uint32_t *)hash, AVB_SHA256_DIGEST_SIZE / 4)) 338*37a7bc39SJason Zhu return -1; 339*37a7bc39SJason Zhu #else 340*37a7bc39SJason Zhu avb_error("Please open the macro!\n"); 341*37a7bc39SJason Zhu return -1; 342*37a7bc39SJason Zhu #endif 343*37a7bc39SJason Zhu return AVB_IO_RESULT_OK; 344*37a7bc39SJason Zhu } 345*37a7bc39SJason Zhu 346*37a7bc39SJason Zhu AvbOps* avb_ops_user_new(void) { 347*37a7bc39SJason Zhu AvbOps* ops; 348*37a7bc39SJason Zhu 349*37a7bc39SJason Zhu ops = calloc(1, sizeof(AvbOps)); 350*37a7bc39SJason Zhu if (ops == NULL) { 351*37a7bc39SJason Zhu avb_error("Error allocating memory for AvbOps.\n"); 352*37a7bc39SJason Zhu goto out; 353*37a7bc39SJason Zhu } 354*37a7bc39SJason Zhu 355*37a7bc39SJason Zhu ops->ab_ops = calloc(1, sizeof(AvbABOps)); 356*37a7bc39SJason Zhu if (ops->ab_ops == NULL) { 357*37a7bc39SJason Zhu avb_error("Error allocating memory for AvbABOps.\n"); 358*37a7bc39SJason Zhu free(ops); 359*37a7bc39SJason Zhu goto out; 360*37a7bc39SJason Zhu } 361*37a7bc39SJason Zhu 362*37a7bc39SJason Zhu ops->atx_ops = calloc(1, sizeof(AvbAtxOps)); 363*37a7bc39SJason Zhu if (ops->atx_ops == NULL) { 364*37a7bc39SJason Zhu avb_error("Error allocating memory for AvbAtxOps.\n"); 365*37a7bc39SJason Zhu free(ops->ab_ops); 366*37a7bc39SJason Zhu free(ops); 367*37a7bc39SJason Zhu goto out; 368*37a7bc39SJason Zhu } 369*37a7bc39SJason Zhu ops->ab_ops->ops = ops; 370*37a7bc39SJason Zhu ops->atx_ops->ops = ops; 371*37a7bc39SJason Zhu 372*37a7bc39SJason Zhu ops->read_from_partition = read_from_partition; 373*37a7bc39SJason Zhu ops->write_to_partition = write_to_partition; 374*37a7bc39SJason Zhu ops->validate_vbmeta_public_key = validate_vbmeta_public_key; 375*37a7bc39SJason Zhu ops->read_rollback_index = read_rollback_index; 376*37a7bc39SJason Zhu ops->write_rollback_index = write_rollback_index; 377*37a7bc39SJason Zhu ops->read_is_device_unlocked = read_is_device_unlocked; 378*37a7bc39SJason Zhu ops->write_is_device_unlocked = write_is_device_unlocked; 379*37a7bc39SJason Zhu ops->get_unique_guid_for_partition = get_unique_guid_for_partition; 380*37a7bc39SJason Zhu ops->get_size_of_partition = get_size_of_partition; 381*37a7bc39SJason Zhu ops->ab_ops->read_ab_metadata = avb_ab_data_read; 382*37a7bc39SJason Zhu ops->ab_ops->write_ab_metadata = avb_ab_data_write; 383*37a7bc39SJason Zhu ops->atx_ops->read_permanent_attributes = avb_read_perm_attr; 384*37a7bc39SJason Zhu ops->atx_ops->read_permanent_attributes_hash = avb_read_perm_attr_hash; 385*37a7bc39SJason Zhu 386*37a7bc39SJason Zhu out: 387*37a7bc39SJason Zhu return ops; 388*37a7bc39SJason Zhu } 389*37a7bc39SJason Zhu 390*37a7bc39SJason Zhu 391*37a7bc39SJason Zhu void avb_ops_user_free(AvbOps* ops) { 392*37a7bc39SJason Zhu free(ops->ab_ops); 393*37a7bc39SJason Zhu free(ops->atx_ops); 394*37a7bc39SJason Zhu free(ops); 395*37a7bc39SJason Zhu } 396