blob: e4c68f955b2f8f24581fdaad03a930765bd75fd4 [file] [log] [blame]
/*
* Copyright 2020, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "TrustyApp.h"
#include <android-base/logging.h>
#include <sys/uio.h>
#include <trusty/tipc.h>
namespace android {
namespace trusty {
// 0x1000 is the message buffer size but we need to leave some space for a protocol header.
// This assures that packets can always be read/written in one read/write operation.
static constexpr const uint32_t kPacketSize = 0x1000 - 32;
enum class PacketType : uint32_t {
SND,
RCV,
ACK,
};
struct PacketHeader {
PacketType type;
uint32_t remaining;
};
const char* toString(PacketType t) {
switch (t) {
case PacketType::SND:
return "SND";
case PacketType::RCV:
return "RCV";
case PacketType::ACK:
return "ACK";
default:
return "UNKNOWN";
}
}
static constexpr const uint32_t kHeaderSize = sizeof(PacketHeader);
static constexpr const uint32_t kPayloadSize = kPacketSize - kHeaderSize;
ssize_t TrustyRpc(int handle, const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin,
uint8_t* iend) {
while (obegin != oend) {
PacketHeader header = {
.type = PacketType::SND,
.remaining = uint32_t(oend - obegin),
};
uint32_t body_size = std::min(kPayloadSize, header.remaining);
iovec iov[] = {
{
.iov_base = &header,
.iov_len = kHeaderSize,
},
{
.iov_base = const_cast<uint8_t*>(obegin),
.iov_len = body_size,
},
};
int rc = writev(handle, iov, 2);
if (!rc) {
PLOG(ERROR) << "Error sending SND message. " << rc;
return rc;
}
obegin += body_size;
rc = read(handle, &header, kHeaderSize);
if (!rc) {
PLOG(ERROR) << "Error reading ACK. " << rc;
return rc;
}
if (header.type != PacketType::ACK || header.remaining != oend - obegin) {
LOG(ERROR) << "malformed ACK";
return -1;
}
}
ssize_t remaining = 0;
auto begin = ibegin;
do {
PacketHeader header = {
.type = PacketType::RCV,
.remaining = 0,
};
iovec iov[] = {
{
.iov_base = &header,
.iov_len = kHeaderSize,
},
{
.iov_base = begin,
.iov_len = uint32_t(iend - begin),
},
};
ssize_t rc = writev(handle, iov, 1);
if (!rc) {
PLOG(ERROR) << "Error sending RCV message. " << rc;
return rc;
}
rc = readv(handle, iov, 2);
if (rc < 0) {
PLOG(ERROR) << "Error reading response. " << rc;
return rc;
}
uint32_t body_size = std::min(kPayloadSize, header.remaining);
if (body_size != rc - kHeaderSize) {
LOG(ERROR) << "Unexpected amount of data: " << rc;
return -1;
}
remaining = header.remaining - body_size;
begin += body_size;
} while (remaining);
return begin - ibegin;
}
TrustyApp::TrustyApp(const std::string& path, const std::string& appname)
: handle_(kInvalidHandle) {
handle_ = tipc_connect(path.c_str(), appname.c_str());
if (handle_ == kInvalidHandle) {
LOG(ERROR) << AT << "failed to connect to Trusty TA \"" << appname << "\" using dev:"
<< "\"" << path << "\"";
}
LOG(INFO) << AT << "succeeded to connect to Trusty TA \"" << appname << "\"";
}
TrustyApp::~TrustyApp() {
if (handle_ != kInvalidHandle) {
tipc_close(handle_);
}
LOG(INFO) << "Done shutting down TrustyApp";
}
} // namespace trusty
} // namespace android