• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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