1 /*
2  * Copyright (C) 2017 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 <cstdint>
18 #include <iomanip>
19 #include <iostream>
20 #include <sstream>
21 #include <string>
22 
23 #include <android-base/file.h>
24 #include <android-base/logging.h>
25 
26 #include <ese/ese.h>
27 ESE_INCLUDE_HW(ESE_HW_NXP_PN80T_NQ_NCI);
28 
29 #include "AlaLib.h"
30 #include "IChannel.h"
31 
32 static struct EseInterface static_ese;
33 
static_ese_open()34 static INT16 static_ese_open() {
35     ese_init((&static_ese), ESE_HW_NXP_PN80T_NQ_NCI);
36     auto res = ese_open(&static_ese, nullptr);
37     if (res != 0) {
38         LOG(ERROR) << "ese_open result: " << (int) res;
39         return EE_ERROR_OPEN_FAIL;
40     }
41     LOG(DEBUG) << "ese_open success";
42     return 1; // arbitrary fake channel
43 }
44 
static_ese_close(INT16)45 static bool static_ese_close(INT16 /* handle */) {
46     LOG(DEBUG) << "ese_close";
47     ese_close(&static_ese);
48     return true;
49 }
50 
log_hexdump(const std::string & prefix,UINT8 * buf,size_t len)51 static void log_hexdump(const std::string& prefix, UINT8 *buf, size_t len) {
52     for (size_t i = 0; i < len; i += 16) {
53         std::ostringstream o;
54         for (size_t j = i; j < i + 16 && j < len; j++) {
55             o << std::hex << std::setw(2) << std::setfill('0') << (int)buf[j] << " ";
56         }
57         LOG(DEBUG) << prefix << ": " << o.str();
58     }
59 }
60 
static_ese_transceive(UINT8 * xmitBuffer,INT32 xmitBufferSize,UINT8 * recvBuffer,INT32 recvBufferMaxSize,INT32 & recvBufferActualSize,INT32)61 static bool static_ese_transceive(UINT8* xmitBuffer, INT32 xmitBufferSize, UINT8* recvBuffer,
62                      INT32 recvBufferMaxSize, INT32& recvBufferActualSize, INT32 /* timeoutMillisec */) {
63     log_hexdump("tx", xmitBuffer, xmitBufferSize);
64     auto res = ese_transceive(&static_ese,
65         xmitBuffer, xmitBufferSize,
66         recvBuffer, recvBufferMaxSize);
67     if (res < 0 || ese_error(&static_ese)) {
68         LOG(ERROR) << "ese_transceive result: " << (int) res
69             << " code " << ese_error_code(&static_ese)
70             << " message: " << ese_error_message(&static_ese);
71         recvBufferActualSize = 0;
72         return false;
73     }
74     recvBufferActualSize = res;
75     log_hexdump("rx", recvBuffer, res);
76     return true;
77 }
78 
static_ese_doeSE_Reset()79 static void static_ese_doeSE_Reset() {
80     LOG(DEBUG) << "static_ese_doeSE_Reset (doing nothing)";
81 }
82 
83 IChannel_t static_ese_ichannel = {
84     static_ese_open,
85     static_ese_close,
86     static_ese_transceive,
87     static_ese_doeSE_Reset,
88     nullptr
89 };
90 
readFileToString(const std::string & filename,std::string * result)91 static bool readFileToString(const std::string& filename, std::string* result) {
92     if (!android::base::ReadFileToString(filename, result)) {
93         PLOG(ERROR) << "Failed to read from " << filename;
94         return false;
95     }
96     return true;
97 }
98 
99 typedef struct ls_update_t {
100     std::string shadata;
101     std::string source;
102     std::string dest;
103 } ls_update_t;
104 
send_ls_update(const ls_update_t & update)105 static bool send_ls_update(const ls_update_t &update) {
106     UINT8 version_buf[4];
107     auto status = ALA_lsGetVersion(version_buf);
108     if (status != STATUS_SUCCESS) {
109         LOG(ERROR) << "ALA_lsGetVersion failed with status " << (int) status;
110         return false;
111     }
112     log_hexdump("version", version_buf, sizeof(version_buf));
113     UINT8 respSW_buf[4];
114     status = ALA_Start(
115         const_cast<char *>(update.source.c_str()),
116         const_cast<char *>(update.dest.c_str()),
117         const_cast<UINT8 *>(reinterpret_cast<const UINT8*>(update.shadata.data())),
118         update.shadata.size(),
119         respSW_buf);
120     if (status != STATUS_SUCCESS) {
121         LOG(ERROR) << "ALA_Start failed with status " << (int) status;
122         return false;
123     }
124     log_hexdump("respSW", respSW_buf, sizeof(respSW_buf));
125     LOG(DEBUG) << "All interactions completed";
126     return true;
127 }
128 
parse_args(char * argv[],ls_update_t * update)129 static bool parse_args(char* argv[], ls_update_t *update) {
130     char **argp = argv + 1;
131     if (*argp == nullptr) {
132         LOG(ERROR) << "No shadata supplied";
133         return false;
134     }
135     if (!readFileToString(*argp, &update->shadata)) {
136         return false;
137     }
138     argp++;
139     if (*argp == nullptr) {
140         LOG(ERROR) << "No source supplied";
141         return false;
142     }
143     update->source = *argp;
144     argp++;
145     if (*argp == nullptr) {
146         LOG(ERROR) << "No dest supplied";
147         return false;
148     }
149     update->dest = *argp;
150     argp++;
151     if (*argp != nullptr) {
152         LOG(ERROR) << "Extra arguments present";
153         return false;
154     }
155     return true;
156 }
157 
ls_update_cli(char * argv[])158 static bool ls_update_cli(char* argv[]) {
159     ls_update_t update;
160     if (!parse_args(argv, &update)) {
161         return false;
162     }
163     auto status = ALA_Init(&static_ese_ichannel);
164     if (status != STATUS_SUCCESS) {
165         LOG(ERROR) << "ALA_Init failed with status " << (int) status;
166         return false;
167     }
168     auto success = send_ls_update(update);
169     if (ALA_DeInit()) {
170         LOG(INFO) << "ALA_DeInit succeeded";
171     } else {
172         LOG(ERROR) << "ALA_DeInit failed";
173         return false;
174     }
175     return success;
176 }
177 
main(int,char * argv[])178 int main(int /* argc */, char* argv[]) {
179     setenv("ANDROID_LOG_TAGS", "*:v", 1); // TODO: remove this line.
180     android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
181     LOG(DEBUG) << "Start of ESE provisioning";
182     return ls_update_cli(argv) ? 0 : -1;
183 }
184