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 | |
37 | static AvbOps* ops = NULL; |
38 | |
39 | static 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 | |
50 | static unsigned int module_getNumberSlots(boot_control_module_t* module) { |
51 | return 2; |
52 | } |
53 | |
54 | static 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 | |
72 | static 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 | |
84 | static 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 | |
93 | static 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 | |
102 | static 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 | |
121 | static 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 | |
138 | static 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 | |
147 | static struct hw_module_methods_t module_methods = { |
148 | .open = NULL, |
149 | }; |
150 | |
151 | boot_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 |