blob: 58f5925dfab84a820c8ff61e758ac5f3ae3b9391 [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.
*/
#define TLOG_TAG "secure_fb_impl"
#include <lib/secure_fb/srv/dev.h>
#include <lib/secure_fb/srv/srv.h>
#include <lib/tipc/tipc.h>
#include <lk/err_ptr.h>
#include <lk/macros.h>
#include <memref.h>
#include <sys/auxv.h>
#include <sys/mman.h>
#include <trusty_ipc.h>
#include <trusty_log.h>
#include <tuple>
#define PAGE_SIZE() (getauxval(AT_PAGESZ))
static constexpr const uint32_t kDeviceWidth = 400;
static constexpr const uint32_t kDeviceHeight = 800;
static constexpr const uint32_t kFbCount = 1;
static constexpr const uint32_t kFbId = 0xdeadbeef;
class SecureFbMockImpl {
private:
struct FbDbEntry {
secure_fb_info fb_info;
handle_t handle;
ptrdiff_t offset;
};
FbDbEntry fb_db_[kFbCount];
public:
int Init(uint32_t width, uint32_t height) {
uint32_t fb_size =
round_up(sizeof(uint32_t) * width * height, PAGE_SIZE());
/*
* Every secure_fb client (of which there can only be one at a time)
* gets the same framebuffer memory. We do this so to prevent running
* out of memory as the number of connections to secure_fb server grows
* over time.
*/
static void* fb_base = memalign(PAGE_SIZE(), fb_size);
if (!fb_base) {
TLOGE("Failed to allocate framebuffer of size: %u\n", fb_size);
return SECURE_FB_ERROR_MEMORY_ALLOCATION;
}
/*
* Create a handle for the buffer by which it can be passed to the TUI
* app for rendering.
*/
static int handle =
memref_create(fb_base, fb_size, PROT_READ | PROT_WRITE);
if (handle < 0) {
TLOGE("Failed to create memref (%d)\n", handle);
free(fb_base);
return SECURE_FB_ERROR_SHARED_MEMORY;
}
fb_db_[0] = {
.fb_info =
{
.buffer = (uint8_t*)fb_base,
.size = fb_size,
.pixel_stride = 4,
.line_stride = 4 * width,
.width = width,
.height = height,
.pixel_format = TTUI_PF_RGBA8,
},
.handle = handle,
};
return SECURE_FB_ERROR_OK;
}
int GetFbs(struct secure_fb_impl_buffers* buffers) {
*buffers = {
.num_fbs = 1,
.fbs[0] =
{
.buffer_id = kFbId,
.handle_index = 0,
.fb_info = fb_db_[0].fb_info,
},
.num_handles = 1,
.handles[0] = fb_db_[0].handle,
};
return SECURE_FB_ERROR_OK;
}
int Display(uint32_t buffer_id) {
if (buffer_id != kFbId) {
return SECURE_FB_ERROR_INVALID_REQUEST;
}
/* This is a no-op in the mock case. */
return SECURE_FB_ERROR_OK;
}
};
secure_fb_handle_t secure_fb_impl_init() {
auto sfb = new SecureFbMockImpl();
sfb->Init(kDeviceWidth, kDeviceHeight);
return sfb;
}
int secure_fb_impl_get_fbs(secure_fb_handle_t sfb_handle,
struct secure_fb_impl_buffers* buffers) {
SecureFbMockImpl* sfb = reinterpret_cast<SecureFbMockImpl*>(sfb_handle);
return sfb->GetFbs(buffers);
}
int secure_fb_impl_display_fb(secure_fb_handle_t sfb_handle,
uint32_t buffer_id) {
SecureFbMockImpl* sfb = reinterpret_cast<SecureFbMockImpl*>(sfb_handle);
return sfb->Display(buffer_id);
}
int secure_fb_impl_release(secure_fb_handle_t sfb_handle) {
SecureFbMockImpl* sfb = reinterpret_cast<SecureFbMockImpl*>(sfb_handle);
delete sfb;
return SECURE_FB_ERROR_OK;
}
int main(void) {
int rc;
struct tipc_hset* hset;
hset = tipc_hset_create();
if (IS_ERR(hset)) {
TLOGE("failed (%d) to create handle set\n", PTR_ERR(hset));
return PTR_ERR(hset);
}
rc = add_secure_fb_service(hset);
if (rc != NO_ERROR) {
TLOGE("failed (%d) to initialize secure_fb mock service\n", rc);
return rc;
}
return tipc_run_event_loop(hset);
}