1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include <errno.h> 26 #include <string.h> 27 28 #include <cutils/properties.h> 29 #include <hardware/boot_control.h> 30 #include <hardware/hardware.h> 31 32 #include <libavb_ab/libavb_ab.h> 33 #include <libavb_user/libavb_user.h> 34 35 static AvbOps* ops = NULL; 36 37 static void module_init(boot_control_module_t* module) { 38 if (ops != NULL) { 39 return; 40 } 41 42 ops = avb_ops_user_new(); 43 if (ops == NULL) { 44 avb_error("Unable to allocate AvbOps instance.\n"); 45 } 46 } 47 48 static unsigned int module_getNumberSlots(boot_control_module_t* module) { 49 return 2; 50 } 51 52 static unsigned int module_getCurrentSlot(boot_control_module_t* module) { 53 char propbuf[PROPERTY_VALUE_MAX]; 54 55 property_get("ro.boot.slot_suffix", propbuf, ""); 56 if (strcmp(propbuf, "_a") == 0) { 57 return 0; 58 } else if (strcmp(propbuf, "_b") == 0) { 59 return 1; 60 } else { 61 avb_errorv("Unexpected slot suffix '", propbuf, "'.\n", NULL); 62 return 0; 63 } 64 return 0; 65 } 66 67 static int module_markBootSuccessful(boot_control_module_t* module) { 68 if (avb_ab_mark_slot_successful(ops->ab_ops, module_getCurrentSlot(module)) == 69 AVB_IO_RESULT_OK) { 70 return 0; 71 } else { 72 return -EIO; 73 } 74 } 75 76 static int module_setActiveBootSlot(boot_control_module_t* module, 77 unsigned int slot) { 78 if (slot >= module_getNumberSlots(module)) { 79 return -EINVAL; 80 } else if (avb_ab_mark_slot_active(ops->ab_ops, slot) == AVB_IO_RESULT_OK) { 81 return 0; 82 } else { 83 return -EIO; 84 } 85 } 86 87 static int module_setSlotAsUnbootable(struct boot_control_module* module, 88 unsigned int slot) { 89 if (slot >= module_getNumberSlots(module)) { 90 return -EINVAL; 91 } else if (avb_ab_mark_slot_unbootable(ops->ab_ops, slot) == 92 AVB_IO_RESULT_OK) { 93 return 0; 94 } else { 95 return -EIO; 96 } 97 } 98 99 static int module_isSlotBootable(struct boot_control_module* module, 100 unsigned int slot) { 101 AvbABData ab_data; 102 bool is_bootable; 103 104 avb_assert(slot < 2); 105 106 if (slot >= module_getNumberSlots(module)) { 107 return -EINVAL; 108 } else if (avb_ab_data_read(ops->ab_ops, &ab_data) != AVB_IO_RESULT_OK) { 109 return -EIO; 110 } 111 112 is_bootable = (ab_data.slots[slot].priority > 0) && 113 (ab_data.slots[slot].successful_boot || 114 (ab_data.slots[slot].tries_remaining > 0)); 115 116 return is_bootable ? 1 : 0; 117 } 118 119 static int module_isSlotMarkedSuccessful(struct boot_control_module* module, 120 unsigned int slot) { 121 AvbABData ab_data; 122 bool is_marked_successful; 123 124 avb_assert(slot < 2); 125 126 if (slot >= module_getNumberSlots(module)) { 127 return -EINVAL; 128 } else if (avb_ab_data_read(ops->ab_ops, &ab_data) != AVB_IO_RESULT_OK) { 129 return -EIO; 130 } 131 132 is_marked_successful = ab_data.slots[slot].successful_boot; 133 134 return is_marked_successful ? 1 : 0; 135 } 136 137 static const char* module_getSuffix(boot_control_module_t* module, 138 unsigned int slot) { 139 static const char* suffix[2] = {"_a", "_b"}; 140 if (slot >= 2) { 141 return NULL; 142 } 143 return suffix[slot]; 144 } 145 146 static struct hw_module_methods_t module_methods = { 147 .open = NULL, 148 }; 149 150 boot_control_module_t HAL_MODULE_INFO_SYM = { 151 .common = 152 { 153 .tag = HARDWARE_MODULE_TAG, 154 .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1, 155 .hal_api_version = HARDWARE_HAL_API_VERSION, 156 .id = BOOT_CONTROL_HARDWARE_MODULE_ID, 157 .name = "AVB implementation of boot_control HAL", 158 .author = "The Android Open Source Project", 159 .methods = &module_methods, 160 }, 161 .init = module_init, 162 .getNumberSlots = module_getNumberSlots, 163 .getCurrentSlot = module_getCurrentSlot, 164 .markBootSuccessful = module_markBootSuccessful, 165 .setActiveBootSlot = module_setActiveBootSlot, 166 .setSlotAsUnbootable = module_setSlotAsUnbootable, 167 .isSlotBootable = module_isSlotBootable, 168 .getSuffix = module_getSuffix, 169 .isSlotMarkedSuccessful = module_isSlotMarkedSuccessful, 170 }; 171