| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Permission is hereby granted, free of charge, to any person |
| * obtaining a copy of this software and associated documentation |
| * files (the "Software"), to deal in the Software without |
| * restriction, including without limitation the rights to use, copy, |
| * modify, merge, publish, distribute, sublicense, and/or sell copies |
| * of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| */ |
| |
| #include <errno.h> |
| #include <string.h> |
| |
| #include <cutils/properties.h> |
| #include <hardware/boot_control.h> |
| #include <hardware/hardware.h> |
| |
| #include <libavb_user/libavb_user.h> |
| |
| static AvbOps* ops = NULL; |
| |
| static void module_init(boot_control_module_t* module) { |
| if (ops != NULL) { |
| return; |
| } |
| |
| ops = avb_ops_user_new(); |
| if (ops == NULL) { |
| avb_error("Unable to allocate AvbOps instance.\n"); |
| } |
| } |
| |
| static unsigned int module_getNumberSlots(boot_control_module_t* module) { |
| return 2; |
| } |
| |
| static unsigned int module_getCurrentSlot(boot_control_module_t* module) { |
| char propbuf[PROPERTY_VALUE_MAX]; |
| |
| property_get("ro.boot.slot_suffix", propbuf, ""); |
| if (strcmp(propbuf, "_a") == 0) { |
| return 0; |
| } else if (strcmp(propbuf, "_b") == 0) { |
| return 1; |
| } else { |
| avb_errorv("Unexpected slot suffix '", propbuf, "'.\n", NULL); |
| return 0; |
| } |
| return 0; |
| } |
| |
| static int module_markBootSuccessful(boot_control_module_t* module) { |
| if (avb_ab_mark_slot_successful(ops->ab_ops, module_getCurrentSlot(module)) == |
| AVB_IO_RESULT_OK) { |
| return 0; |
| } else { |
| return -EIO; |
| } |
| } |
| |
| static int module_setActiveBootSlot(boot_control_module_t* module, |
| unsigned int slot) { |
| if (avb_ab_mark_slot_active(ops->ab_ops, slot) == AVB_IO_RESULT_OK) { |
| return 0; |
| } else { |
| return -EIO; |
| } |
| } |
| |
| static int module_setSlotAsUnbootable(struct boot_control_module* module, |
| unsigned int slot) { |
| if (avb_ab_mark_slot_unbootable(ops->ab_ops, slot) == AVB_IO_RESULT_OK) { |
| return 0; |
| } else { |
| return -EIO; |
| } |
| } |
| |
| static int module_isSlotBootable(struct boot_control_module* module, |
| unsigned int slot) { |
| AvbABData ab_data; |
| bool is_bootable; |
| |
| avb_assert(slot < 2); |
| |
| if (avb_ab_data_read(ops->ab_ops, &ab_data) != AVB_IO_RESULT_OK) { |
| return -EIO; |
| } |
| |
| is_bootable = (ab_data.slots[slot].priority > 0) && |
| (ab_data.slots[slot].successful_boot || |
| (ab_data.slots[slot].tries_remaining > 0)); |
| |
| return is_bootable ? 1 : 0; |
| } |
| |
| static int module_isSlotMarkedSuccessful(struct boot_control_module* module, |
| unsigned int slot) { |
| AvbABData ab_data; |
| bool is_marked_successful; |
| |
| avb_assert(slot < 2); |
| |
| if (avb_ab_data_read(ops->ab_ops, &ab_data) != AVB_IO_RESULT_OK) { |
| return -EIO; |
| } |
| |
| is_marked_successful = ab_data.slots[slot].successful_boot; |
| |
| return is_marked_successful ? 1 : 0; |
| } |
| |
| static const char* module_getSuffix(boot_control_module_t* module, |
| unsigned int slot) { |
| static const char* suffix[2] = {"_a", "_b"}; |
| if (slot >= 2) { |
| return NULL; |
| } |
| return suffix[slot]; |
| } |
| |
| static struct hw_module_methods_t module_methods = { |
| .open = NULL, |
| }; |
| |
| boot_control_module_t HAL_MODULE_INFO_SYM = { |
| .common = |
| { |
| .tag = HARDWARE_MODULE_TAG, |
| .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1, |
| .hal_api_version = HARDWARE_HAL_API_VERSION, |
| .id = BOOT_CONTROL_HARDWARE_MODULE_ID, |
| .name = "AVB implementation of boot_control HAL", |
| .author = "The Android Open Source Project", |
| .methods = &module_methods, |
| }, |
| .init = module_init, |
| .getNumberSlots = module_getNumberSlots, |
| .getCurrentSlot = module_getCurrentSlot, |
| .markBootSuccessful = module_markBootSuccessful, |
| .setActiveBootSlot = module_setActiveBootSlot, |
| .setSlotAsUnbootable = module_setSlotAsUnbootable, |
| .isSlotBootable = module_isSlotBootable, |
| .getSuffix = module_getSuffix, |
| .isSlotMarkedSuccessful = module_isSlotMarkedSuccessful, |
| }; |