Home | History | Annotate | Download | only in hal
      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