/* * 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 #include #include #include #include #include #include #include #include #include #include #include #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; static handle_t secure_dpu_handle = INVALID_IPC_HANDLE; class SecureFbMockImpl { private: struct FbDbEntry { secure_fb_info fb_info; secure_dpu_buf_info buf_info; handle_t handle = INVALID_IPC_HANDLE; ptrdiff_t offset; }; FbDbEntry fb_db_[kFbCount]; public: ~SecureFbMockImpl() { if (fb_db_[0].handle != INVALID_IPC_HANDLE) { close(fb_db_[0].handle); } int rc = munmap(fb_db_[0].fb_info.buffer, fb_db_[0].fb_info.size); if (rc < 0) { TLOGE("Failed to do munmap\n"); } if (secure_dpu_release_buffer(&fb_db_[0].buf_info) < 0) { TLOGE("Failed to free framebuffer\n"); } if (secure_dpu_stop_secure_display(secure_dpu_handle) < 0) { TLOGE("Failed to stop secure_display\n"); } } int Init(uint32_t width, uint32_t height) { if (secure_dpu_start_secure_display(secure_dpu_handle) < 0) { TLOGE("Failed to start secure_display\n"); return SECURE_FB_ERROR_UNINITIALIZED; } uint32_t fb_size = round_up(sizeof(uint32_t) * width * height, PAGE_SIZE()); secure_dpu_buf_info buf_info; if (secure_dpu_allocate_buffer(secure_dpu_handle, (size_t)fb_size, &buf_info) < 0) { TLOGE("Failed to allocate framebuffer of size: %u\n", fb_size); return SECURE_FB_ERROR_MEMORY_ALLOCATION; } void* fb_base = mmap(0, (size_t)fb_size, PROT_READ | PROT_WRITE, 0, buf_info.handle, 0); if (fb_base == MAP_FAILED) { TLOGE("Error when calling mmap()\n"); return SECURE_FB_ERROR_SHARED_MEMORY; } /* * Create a handle for the buffer by which it can be passed to the TUI * app for rendering. */ int handle = memref_create(fb_base, fb_size, PROT_READ | PROT_WRITE); if (handle < 0) { TLOGE("Failed to create memref (%d)\n", handle); 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, .rotation = TTUI_DRAW_ROTATION_0, .display_index = 0}, .buf_info = buf_info, .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; } }; static secure_fb_handle_t secure_fb_impl_init() { auto sfb = new SecureFbMockImpl(); auto rc = sfb->Init(kDeviceWidth, kDeviceHeight); if (rc != SECURE_FB_ERROR_OK) { delete sfb; return NULL; } return sfb; } static int secure_fb_impl_get_fbs(secure_fb_handle_t sfb_handle, struct secure_fb_impl_buffers* buffers) { SecureFbMockImpl* sfb = reinterpret_cast(sfb_handle); return sfb->GetFbs(buffers); } static int secure_fb_impl_display_fb(secure_fb_handle_t sfb_handle, uint32_t buffer_id) { SecureFbMockImpl* sfb = reinterpret_cast(sfb_handle); return sfb->Display(buffer_id); } static int secure_fb_impl_release(secure_fb_handle_t sfb_handle) { SecureFbMockImpl* sfb = reinterpret_cast(sfb_handle); delete sfb; return SECURE_FB_ERROR_OK; } static const struct secure_fb_impl_ops ops = { .init = secure_fb_impl_init, .get_fbs = secure_fb_impl_get_fbs, .display_fb = secure_fb_impl_display_fb, .release = secure_fb_impl_release, }; 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_dpu_service(hset, &secure_dpu_handle); if (rc != NO_ERROR) { TLOGE("failed (%d) to initialize secure_dpu mock service\n", rc); return rc; } rc = add_secure_fb_service(hset, &ops, 1); if (rc != NO_ERROR) { TLOGE("failed (%d) to initialize secure_fb mock service\n", rc); return rc; } return tipc_run_event_loop(hset); }