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