• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
module_init(boot_control_module_t * module)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 
module_getNumberSlots(boot_control_module_t * module)47 static unsigned int module_getNumberSlots(boot_control_module_t* module) {
48   return 2;
49 }
50 
module_getCurrentSlot(boot_control_module_t * module)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 
module_markBootSuccessful(boot_control_module_t * module)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 
module_setActiveBootSlot(boot_control_module_t * module,unsigned int slot)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 
module_setSlotAsUnbootable(struct boot_control_module * module,unsigned int slot)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 
module_isSlotBootable(struct boot_control_module * module,unsigned int slot)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 
module_isSlotMarkedSuccessful(struct boot_control_module * module,unsigned int slot)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 
module_getSuffix(boot_control_module_t * module,unsigned int slot)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