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> 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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