1 /*
2  * Copyright 2020, 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 #define TLOG_TAG "secure_fb_impl"
18 
19 #include <lib/secure_dpu/secure_dpu.h>
20 #include <lib/secure_fb/srv/dev.h>
21 #include <lib/secure_fb/srv/srv.h>
22 #include <lib/tipc/tipc.h>
23 #include <lk/err_ptr.h>
24 #include <lk/macros.h>
25 #include <sys/auxv.h>
26 #include <sys/mman.h>
27 #include <trusty/memref.h>
28 #include <trusty_ipc.h>
29 #include <trusty_log.h>
30 
31 #include <tuple>
32 
33 #define PAGE_SIZE() (getauxval(AT_PAGESZ))
34 
35 static constexpr const uint32_t kDeviceWidth = 400;
36 static constexpr const uint32_t kDeviceHeight = 800;
37 static constexpr const uint32_t kFbCount = 1;
38 static constexpr const uint32_t kFbId = 0xdeadbeef;
39 
40 static handle_t secure_dpu_handle = INVALID_IPC_HANDLE;
41 
42 class SecureFbMockImpl {
43 private:
44     struct FbDbEntry {
45         secure_fb_info fb_info;
46         secure_dpu_buf_info buf_info;
47         handle_t handle = INVALID_IPC_HANDLE;
48         ptrdiff_t offset;
49     };
50 
51     FbDbEntry fb_db_[kFbCount];
52 
53 public:
~SecureFbMockImpl()54     ~SecureFbMockImpl() {
55         if (fb_db_[0].handle != INVALID_IPC_HANDLE) {
56             close(fb_db_[0].handle);
57         }
58         int rc = munmap(fb_db_[0].fb_info.buffer, fb_db_[0].fb_info.size);
59         if (rc < 0) {
60             TLOGE("Failed to do munmap\n");
61         }
62         if (secure_dpu_release_buffer(&fb_db_[0].buf_info) < 0) {
63             TLOGE("Failed to free framebuffer\n");
64         }
65         if (secure_dpu_stop_secure_display(secure_dpu_handle) < 0) {
66             TLOGE("Failed to stop secure_display\n");
67         }
68     }
69 
Init(uint32_t width,uint32_t height)70     int Init(uint32_t width, uint32_t height) {
71         if (secure_dpu_start_secure_display(secure_dpu_handle) < 0) {
72             TLOGE("Failed to start secure_display\n");
73             return SECURE_FB_ERROR_UNINITIALIZED;
74         }
75 
76         uint32_t fb_size =
77                 round_up(sizeof(uint32_t) * width * height, PAGE_SIZE());
78         secure_dpu_buf_info buf_info;
79 
80         if (secure_dpu_allocate_buffer(secure_dpu_handle,
81                                        (size_t)fb_size,
82                                        &buf_info) < 0) {
83             TLOGE("Failed to allocate framebuffer of size: %u\n", fb_size);
84             return SECURE_FB_ERROR_MEMORY_ALLOCATION;
85         }
86         void* fb_base = mmap(0, (size_t)fb_size, PROT_READ | PROT_WRITE, 0,
87                              buf_info.handle, 0);
88         if (fb_base == MAP_FAILED) {
89             TLOGE("Error when calling mmap()\n");
90             return SECURE_FB_ERROR_SHARED_MEMORY;
91         }
92 
93         /*
94          * Create a handle for the buffer by which it can be passed to the TUI
95          * app for rendering.
96          */
97         int handle =
98                 memref_create(fb_base, fb_size, PROT_READ | PROT_WRITE);
99         if (handle < 0) {
100             TLOGE("Failed to create memref (%d)\n", handle);
101             return SECURE_FB_ERROR_SHARED_MEMORY;
102         }
103 
104         fb_db_[0] = {
105                 .fb_info = {.buffer = (uint8_t*)fb_base,
106                             .size = fb_size,
107                             .pixel_stride = 4,
108                             .line_stride = 4 * width,
109                             .width = width,
110                             .height = height,
111                             .pixel_format = TTUI_PF_RGBA8,
112                             .rotation = TTUI_DRAW_ROTATION_0,
113                             .display_index = 0},
114                 .buf_info = buf_info,
115                 .handle = handle,
116         };
117 
118         return SECURE_FB_ERROR_OK;
119     }
120 
GetFbs(struct secure_fb_impl_buffers * buffers)121     int GetFbs(struct secure_fb_impl_buffers* buffers) {
122         *buffers = {
123                 .num_fbs = 1,
124                 .fbs[0] =
125                         {
126                                 .buffer_id = kFbId,
127                                 .handle_index = 0,
128                                 .fb_info = fb_db_[0].fb_info,
129                         },
130                 .num_handles = 1,
131                 .handles[0] = fb_db_[0].handle,
132         };
133         return SECURE_FB_ERROR_OK;
134     }
135 
Display(uint32_t buffer_id)136     int Display(uint32_t buffer_id) {
137         if (buffer_id != kFbId) {
138             return SECURE_FB_ERROR_INVALID_REQUEST;
139         }
140 
141         /* This is a no-op in the mock case. */
142         return SECURE_FB_ERROR_OK;
143     }
144 };
145 
secure_fb_impl_init()146 static secure_fb_handle_t secure_fb_impl_init() {
147     auto sfb = new SecureFbMockImpl();
148     auto rc = sfb->Init(kDeviceWidth, kDeviceHeight);
149     if (rc != SECURE_FB_ERROR_OK) {
150         delete sfb;
151         return NULL;
152     }
153     return sfb;
154 }
155 
secure_fb_impl_get_fbs(secure_fb_handle_t sfb_handle,struct secure_fb_impl_buffers * buffers)156 static int secure_fb_impl_get_fbs(secure_fb_handle_t sfb_handle,
157                                   struct secure_fb_impl_buffers* buffers) {
158     SecureFbMockImpl* sfb = reinterpret_cast<SecureFbMockImpl*>(sfb_handle);
159     return sfb->GetFbs(buffers);
160 }
161 
secure_fb_impl_display_fb(secure_fb_handle_t sfb_handle,uint32_t buffer_id)162 static int secure_fb_impl_display_fb(secure_fb_handle_t sfb_handle,
163                                      uint32_t buffer_id) {
164     SecureFbMockImpl* sfb = reinterpret_cast<SecureFbMockImpl*>(sfb_handle);
165     return sfb->Display(buffer_id);
166 }
167 
secure_fb_impl_release(secure_fb_handle_t sfb_handle)168 static int secure_fb_impl_release(secure_fb_handle_t sfb_handle) {
169     SecureFbMockImpl* sfb = reinterpret_cast<SecureFbMockImpl*>(sfb_handle);
170     delete sfb;
171     return SECURE_FB_ERROR_OK;
172 }
173 
174 static const struct secure_fb_impl_ops ops = {
175         .init = secure_fb_impl_init,
176         .get_fbs = secure_fb_impl_get_fbs,
177         .display_fb = secure_fb_impl_display_fb,
178         .release = secure_fb_impl_release,
179 };
180 
main(void)181 int main(void) {
182     int rc;
183     struct tipc_hset* hset;
184 
185     hset = tipc_hset_create();
186     if (IS_ERR(hset)) {
187         TLOGE("failed (%d) to create handle set\n", PTR_ERR(hset));
188         return PTR_ERR(hset);
189     }
190 
191     rc = add_secure_dpu_service(hset, &secure_dpu_handle);
192     if (rc != NO_ERROR) {
193         TLOGE("failed (%d) to initialize secure_dpu mock service\n", rc);
194         return rc;
195     }
196 
197     rc = add_secure_fb_service(hset, &ops, 1);
198     if (rc != NO_ERROR) {
199         TLOGE("failed (%d) to initialize secure_fb mock service\n", rc);
200         return rc;
201     }
202 
203     return tipc_run_event_loop(hset);
204 }
205