1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <nvram/hal/nvram_device_adapter.h>
18
19 #include <string.h>
20
21 #include <algorithm>
22 #include <type_traits>
23 #include <utility>
24
25 namespace nvram {
26 namespace {
27
28 // Executes an operation on the |NvramDeviceAdapter| corresponding to |device|.
29 // |command| identifies the type of operation, |request_payload| provides the
30 // input parameters. Output parameters are stored in |response_payload|, and the
31 // the nvram operation result code is returned.
32 template <nvram::Command command,
33 typename RequestPayload,
34 typename ResponsePayload>
Execute(const nvram_device_t * device,RequestPayload && request_payload,ResponsePayload * response_payload)35 nvram_result_t Execute(const nvram_device_t* device,
36 RequestPayload&& request_payload,
37 ResponsePayload* response_payload) {
38 NvramDeviceAdapter* adapter = reinterpret_cast<NvramDeviceAdapter*>(
39 const_cast<nvram_device_t*>(device));
40
41 nvram::Request request;
42 request.payload.Activate<command>() = std::move(request_payload);
43 nvram::Response response;
44 adapter->nvram_implementation()->Execute(request, &response);
45 if (response.result != NV_RESULT_SUCCESS) {
46 return response.result;
47 }
48
49 ResponsePayload* response_payload_ptr = response.payload.get<command>();
50 if (!response_payload_ptr) {
51 return NV_RESULT_INTERNAL_ERROR;
52 }
53 *response_payload = std::move(*response_payload_ptr);
54
55 return NV_RESULT_SUCCESS;
56 }
57
58 // All the HAL methods need to be callable from C code.
59 extern "C" {
60
device_get_total_size_in_bytes(const nvram_device_t * device,uint64_t * total_size)61 nvram_result_t device_get_total_size_in_bytes(const nvram_device_t* device,
62 uint64_t* total_size) {
63 nvram::GetInfoRequest get_info_request;
64 nvram::GetInfoResponse get_info_response;
65 nvram_result_t result = Execute<nvram::COMMAND_GET_INFO>(
66 device, std::move(get_info_request), &get_info_response);
67 *total_size = get_info_response.total_size;
68 return result;
69 }
70
device_get_available_size_in_bytes(const nvram_device_t * device,uint64_t * available_size)71 nvram_result_t device_get_available_size_in_bytes(const nvram_device_t* device,
72 uint64_t* available_size) {
73 nvram::GetInfoRequest get_info_request;
74 nvram::GetInfoResponse get_info_response;
75 nvram_result_t result = Execute<nvram::COMMAND_GET_INFO>(
76 device, std::move(get_info_request), &get_info_response);
77 *available_size = get_info_response.available_size;
78 return result;
79 }
80
device_get_max_space_size_in_bytes(const nvram_device_t * device,uint64_t * max_space_size)81 nvram_result_t device_get_max_space_size_in_bytes(const nvram_device_t* device,
82 uint64_t* max_space_size) {
83 nvram::GetInfoRequest get_info_request;
84 nvram::GetInfoResponse get_info_response;
85 nvram_result_t result = Execute<nvram::COMMAND_GET_INFO>(
86 device, std::move(get_info_request), &get_info_response);
87 *max_space_size = get_info_response.max_space_size;
88 return result;
89 }
90
device_get_max_spaces(const nvram_device_t * device,uint32_t * num_spaces)91 nvram_result_t device_get_max_spaces(const nvram_device_t* device,
92 uint32_t* num_spaces) {
93 nvram::GetInfoRequest get_info_request;
94 nvram::GetInfoResponse get_info_response;
95 nvram_result_t result = Execute<nvram::COMMAND_GET_INFO>(
96 device, std::move(get_info_request), &get_info_response);
97 *num_spaces = get_info_response.max_spaces;
98 return result;
99 }
100
device_get_space_list(const nvram_device_t * device,uint32_t max_list_size,uint32_t * space_index_list,uint32_t * list_size)101 nvram_result_t device_get_space_list(const nvram_device_t* device,
102 uint32_t max_list_size,
103 uint32_t* space_index_list,
104 uint32_t* list_size) {
105 nvram::GetInfoRequest get_info_request;
106 nvram::GetInfoResponse get_info_response;
107 nvram_result_t result = Execute<nvram::COMMAND_GET_INFO>(
108 device, std::move(get_info_request), &get_info_response);
109
110 if (space_index_list) {
111 *list_size = std::min(get_info_response.space_list.size(),
112 static_cast<size_t>(max_list_size));
113 for (size_t i = 0; i < *list_size; ++i) {
114 space_index_list[i] = get_info_response.space_list[i];
115 }
116 } else {
117 *list_size = get_info_response.space_list.size();
118 }
119
120 return result;
121 }
122
device_get_space_size(const nvram_device_t * device,uint32_t index,uint64_t * size)123 nvram_result_t device_get_space_size(const nvram_device_t* device,
124 uint32_t index,
125 uint64_t* size) {
126 nvram::GetSpaceInfoRequest get_space_info_request;
127 get_space_info_request.index = index;
128 nvram::GetSpaceInfoResponse get_space_info_response;
129 nvram_result_t result = Execute<nvram::COMMAND_GET_SPACE_INFO>(
130 device, std::move(get_space_info_request), &get_space_info_response);
131 *size = get_space_info_response.size;
132 return result;
133 }
134
device_get_space_controls(const nvram_device_t * device,uint32_t index,uint32_t max_list_size,nvram_control_t * control_list,uint32_t * list_size)135 nvram_result_t device_get_space_controls(const nvram_device_t* device,
136 uint32_t index,
137 uint32_t max_list_size,
138 nvram_control_t* control_list,
139 uint32_t* list_size) {
140 nvram::GetSpaceInfoRequest get_space_info_request;
141 get_space_info_request.index = index;
142 nvram::GetSpaceInfoResponse get_space_info_response;
143 nvram_result_t result = Execute<nvram::COMMAND_GET_SPACE_INFO>(
144 device, std::move(get_space_info_request), &get_space_info_response);
145
146 if (control_list) {
147 *list_size = std::min(get_space_info_response.controls.size(),
148 static_cast<size_t>(max_list_size));
149 for (size_t i = 0; i < *list_size; ++i) {
150 control_list[i] = get_space_info_response.controls[i];
151 }
152 } else {
153 *list_size = get_space_info_response.controls.size();
154 }
155
156 return result;
157 }
158
device_is_space_locked(const nvram_device_t * device,uint32_t index,int * write_lock_enabled,int * read_lock_enabled)159 nvram_result_t device_is_space_locked(const nvram_device_t* device,
160 uint32_t index,
161 int* write_lock_enabled,
162 int* read_lock_enabled) {
163 nvram::GetSpaceInfoRequest get_space_info_request;
164 get_space_info_request.index = index;
165 nvram::GetSpaceInfoResponse get_space_info_response;
166 nvram_result_t result = Execute<nvram::COMMAND_GET_SPACE_INFO>(
167 device, std::move(get_space_info_request), &get_space_info_response);
168 *write_lock_enabled = get_space_info_response.write_locked;
169 *read_lock_enabled = get_space_info_response.read_locked;
170 return result;
171 }
172
device_create_space(const nvram_device_t * device,uint32_t index,uint64_t size_in_bytes,const nvram_control_t * control_list,uint32_t list_size,const uint8_t * authorization_value,uint32_t authorization_value_size)173 nvram_result_t device_create_space(const nvram_device_t* device,
174 uint32_t index,
175 uint64_t size_in_bytes,
176 const nvram_control_t* control_list,
177 uint32_t list_size,
178 const uint8_t* authorization_value,
179 uint32_t authorization_value_size) {
180 nvram::CreateSpaceRequest create_space_request;
181 create_space_request.index = index;
182 create_space_request.size = size_in_bytes;
183 if (!create_space_request.controls.Resize(list_size)) {
184 return NV_RESULT_INTERNAL_ERROR;
185 }
186 for (size_t i = 0; i < list_size; ++i) {
187 create_space_request.controls[i] = control_list[i];
188 }
189 if (!create_space_request.authorization_value.Assign(
190 authorization_value, authorization_value_size)) {
191 return NV_RESULT_INTERNAL_ERROR;
192 }
193 nvram::CreateSpaceResponse create_space_response;
194 return Execute<nvram::COMMAND_CREATE_SPACE>(
195 device, std::move(create_space_request), &create_space_response);
196 }
197
device_delete_space(const nvram_device_t * device,uint32_t index,const uint8_t * authorization_value,uint32_t authorization_value_size)198 nvram_result_t device_delete_space(const nvram_device_t* device,
199 uint32_t index,
200 const uint8_t* authorization_value,
201 uint32_t authorization_value_size) {
202 nvram::DeleteSpaceRequest delete_space_request;
203 delete_space_request.index = index;
204 if (!delete_space_request.authorization_value.Assign(
205 authorization_value, authorization_value_size)) {
206 return NV_RESULT_INTERNAL_ERROR;
207 }
208 nvram::DeleteSpaceResponse delete_space_response;
209 return Execute<nvram::COMMAND_DELETE_SPACE>(
210 device, std::move(delete_space_request), &delete_space_response);
211 }
212
device_disable_create(const nvram_device_t * device)213 nvram_result_t device_disable_create(const nvram_device_t* device) {
214 nvram::DisableCreateRequest disable_create_request;
215 nvram::DisableCreateResponse disable_create_response;
216 return Execute<nvram::COMMAND_DISABLE_CREATE>(
217 device, std::move(disable_create_request), &disable_create_response);
218 }
219
device_write_space(const nvram_device_t * device,uint32_t index,const uint8_t * buffer,uint64_t buffer_size,const uint8_t * authorization_value,uint32_t authorization_value_size)220 nvram_result_t device_write_space(const nvram_device_t* device,
221 uint32_t index,
222 const uint8_t* buffer,
223 uint64_t buffer_size,
224 const uint8_t* authorization_value,
225 uint32_t authorization_value_size) {
226 nvram::WriteSpaceRequest write_space_request;
227 write_space_request.index = index;
228 if (!write_space_request.buffer.Assign(buffer, buffer_size) ||
229 !write_space_request.authorization_value.Assign(
230 authorization_value, authorization_value_size)) {
231 return NV_RESULT_INTERNAL_ERROR;
232 }
233 nvram::WriteSpaceResponse write_space_response;
234 return Execute<nvram::COMMAND_WRITE_SPACE>(
235 device, std::move(write_space_request), &write_space_response);
236 }
237
device_read_space(const nvram_device_t * device,uint32_t index,uint64_t num_bytes_to_read,const uint8_t * authorization_value,uint32_t authorization_value_size,uint8_t * buffer,uint64_t * bytes_read)238 nvram_result_t device_read_space(const nvram_device_t* device,
239 uint32_t index,
240 uint64_t num_bytes_to_read,
241 const uint8_t* authorization_value,
242 uint32_t authorization_value_size,
243 uint8_t* buffer,
244 uint64_t* bytes_read) {
245 nvram::ReadSpaceRequest read_space_request;
246 read_space_request.index = index;
247 if (!read_space_request.authorization_value.Assign(
248 authorization_value, authorization_value_size)) {
249 return NV_RESULT_INTERNAL_ERROR;
250 }
251 nvram::ReadSpaceResponse read_space_response;
252 nvram_result_t result = Execute<nvram::COMMAND_READ_SPACE>(
253 device, std::move(read_space_request), &read_space_response);
254 *bytes_read = std::min(static_cast<size_t>(num_bytes_to_read),
255 read_space_response.buffer.size());
256 memcpy(buffer, read_space_response.buffer.data(), *bytes_read);
257 return result;
258 }
259
device_enable_write_lock(const nvram_device_t * device,uint32_t index,const uint8_t * authorization_value,uint32_t authorization_value_size)260 nvram_result_t device_enable_write_lock(const nvram_device_t* device,
261 uint32_t index,
262 const uint8_t* authorization_value,
263 uint32_t authorization_value_size) {
264 nvram::LockSpaceWriteRequest lock_space_write_request;
265 lock_space_write_request.index = index;
266 if (!lock_space_write_request.authorization_value.Assign(
267 authorization_value, authorization_value_size)) {
268 return NV_RESULT_INTERNAL_ERROR;
269 }
270 nvram::LockSpaceWriteResponse lock_space_write_response;
271 return Execute<nvram::COMMAND_LOCK_SPACE_WRITE>(
272 device, std::move(lock_space_write_request), &lock_space_write_response);
273 }
274
device_enable_read_lock(const nvram_device_t * device,uint32_t index,const uint8_t * authorization_value,uint32_t authorization_value_size)275 nvram_result_t device_enable_read_lock(const nvram_device_t* device,
276 uint32_t index,
277 const uint8_t* authorization_value,
278 uint32_t authorization_value_size) {
279 nvram::LockSpaceReadRequest lock_space_read_request;
280 lock_space_read_request.index = index;
281 if (!lock_space_read_request.authorization_value.Assign(
282 authorization_value, authorization_value_size)) {
283 return NV_RESULT_INTERNAL_ERROR;
284 }
285 nvram::LockSpaceReadResponse lock_space_read_response;
286 return Execute<nvram::COMMAND_LOCK_SPACE_READ>(
287 device, std::move(lock_space_read_request), &lock_space_read_response);
288 }
289
device_nvram_device_close(struct hw_device_t * device)290 int device_nvram_device_close(struct hw_device_t* device) {
291 delete reinterpret_cast<NvramDeviceAdapter*>(
292 reinterpret_cast<nvram_device_t*>(device));
293 return 0;
294 }
295
296 } // extern "C"
297 } // namespace
298
NvramDeviceAdapter(const hw_module_t * module,NvramImplementation * implementation)299 NvramDeviceAdapter::NvramDeviceAdapter(const hw_module_t* module,
300 NvramImplementation* implementation)
301 : implementation_(implementation) {
302 memset(&device_, 0, sizeof(nvram_device_t));
303
304 device_.common.tag = HARDWARE_DEVICE_TAG;
305 device_.common.version = NVRAM_DEVICE_API_VERSION_1_1;
306 device_.common.module = const_cast<hw_module_t *>(module);
307 device_.common.close = device_nvram_device_close;
308
309 device_.get_total_size_in_bytes = device_get_total_size_in_bytes;
310 device_.get_available_size_in_bytes = device_get_available_size_in_bytes;
311 device_.get_max_space_size_in_bytes = device_get_max_space_size_in_bytes;
312 device_.get_max_spaces = device_get_max_spaces;
313 device_.get_space_list = device_get_space_list;
314 device_.get_space_size = device_get_space_size;
315 device_.get_space_controls = device_get_space_controls;
316 device_.is_space_locked = device_is_space_locked;
317 device_.create_space = device_create_space;
318 device_.delete_space = device_delete_space;
319 device_.disable_create = device_disable_create;
320 device_.write_space = device_write_space;
321 device_.read_space = device_read_space;
322 device_.enable_write_lock = device_enable_write_lock;
323 device_.enable_read_lock = device_enable_read_lock;
324 }
325
326 } // namespace nvram
327