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_user/libavb_user.h> 33 34 static AvbOps* ops = NULL; 35 36 static void module_init(boot_control_module_t* module) { 37 if (ops != NULL) { 38 return; 39 } 40 41 ops = avb_ops_user_new(); 42 if (ops == NULL) { 43 avb_error("Unable to allocate AvbOps instance.\n"); 44 } 45 } 46 47 static unsigned int module_getNumberSlots(boot_control_module_t* module) { 48 return 2; 49 } 50 51 static unsigned int module_getCurrentSlot(boot_control_module_t* module) { 52 char propbuf[PROPERTY_VALUE_MAX]; 53 54 property_get("ro.boot.slot_suffix", propbuf, ""); 55 if (strcmp(propbuf, "_a") == 0) { 56 return 0; 57 } else if (strcmp(propbuf, "_b") == 0) { 58 return 1; 59 } else { 60 avb_errorv("Unexpected slot suffix '", propbuf, "'.\n", NULL); 61 return 0; 62 } 63 return 0; 64 } 65 66 static int module_markBootSuccessful(boot_control_module_t* module) { 67 if (avb_ab_mark_slot_successful(ops->ab_ops, module_getCurrentSlot(module)) == 68 AVB_IO_RESULT_OK) { 69 return 0; 70 } else { 71 return -EIO; 72 } 73 } 74 75 static int module_setActiveBootSlot(boot_control_module_t* module, 76 unsigned int slot) { 77 if (avb_ab_mark_slot_active(ops->ab_ops, slot) == AVB_IO_RESULT_OK) { 78 return 0; 79 } else { 80 return -EIO; 81 } 82 } 83 84 static int module_setSlotAsUnbootable(struct boot_control_module* module, 85 unsigned int slot) { 86 if (avb_ab_mark_slot_unbootable(ops->ab_ops, slot) == AVB_IO_RESULT_OK) { 87 return 0; 88 } else { 89 return -EIO; 90 } 91 } 92 93 static int module_isSlotBootable(struct boot_control_module* module, 94 unsigned int slot) { 95 AvbABData ab_data; 96 bool is_bootable; 97 98 avb_assert(slot < 2); 99 100 if (avb_ab_data_read(ops->ab_ops, &ab_data) != AVB_IO_RESULT_OK) { 101 return -EIO; 102 } 103 104 is_bootable = (ab_data.slots[slot].priority > 0) && 105 (ab_data.slots[slot].successful_boot || 106 (ab_data.slots[slot].tries_remaining > 0)); 107 108 return is_bootable ? 1 : 0; 109 } 110 111 static int module_isSlotMarkedSuccessful(struct boot_control_module* module, 112 unsigned int slot) { 113 AvbABData ab_data; 114 bool is_marked_successful; 115 116 avb_assert(slot < 2); 117 118 if (avb_ab_data_read(ops->ab_ops, &ab_data) != AVB_IO_RESULT_OK) { 119 return -EIO; 120 } 121 122 is_marked_successful = ab_data.slots[slot].successful_boot; 123 124 return is_marked_successful ? 1 : 0; 125 } 126 127 static const char* module_getSuffix(boot_control_module_t* module, 128 unsigned int slot) { 129 static const char* suffix[2] = {"_a", "_b"}; 130 if (slot >= 2) { 131 return NULL; 132 } 133 return suffix[slot]; 134 } 135 136 static struct hw_module_methods_t module_methods = { 137 .open = NULL, 138 }; 139 140 boot_control_module_t HAL_MODULE_INFO_SYM = { 141 .common = 142 { 143 .tag = HARDWARE_MODULE_TAG, 144 .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1, 145 .hal_api_version = HARDWARE_HAL_API_VERSION, 146 .id = BOOT_CONTROL_HARDWARE_MODULE_ID, 147 .name = "AVB implementation of boot_control HAL", 148 .author = "The Android Open Source Project", 149 .methods = &module_methods, 150 }, 151 .init = module_init, 152 .getNumberSlots = module_getNumberSlots, 153 .getCurrentSlot = module_getCurrentSlot, 154 .markBootSuccessful = module_markBootSuccessful, 155 .setActiveBootSlot = module_setActiveBootSlot, 156 .setSlotAsUnbootable = module_setSlotAsUnbootable, 157 .isSlotBootable = module_isSlotBootable, 158 .getSuffix = module_getSuffix, 159 .isSlotMarkedSuccessful = module_isSlotMarkedSuccessful, 160 }; 161