Home | History | Annotate | Download | only in boot_control
      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