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