xref: /aosp_15_r20/trusty/kernel/lib/dtb_service/dtb_service.cpp (revision 344aa361028b423587d4ef3fa52a23d194628137)
1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker  * Copyright (c) 2022, Google Inc. All rights reserved
3*344aa361SAndroid Build Coastguard Worker  *
4*344aa361SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker  * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker  * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker  * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker  * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker  * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker  * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker  *
12*344aa361SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker  * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker  *
15*344aa361SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker  */
23*344aa361SAndroid Build Coastguard Worker 
24*344aa361SAndroid Build Coastguard Worker /* Guards uses of trusty/kernel/lib/shared/binder_discover */
25*344aa361SAndroid Build Coastguard Worker #define ENABLE_KERNEL_BINDER (0)
26*344aa361SAndroid Build Coastguard Worker 
27*344aa361SAndroid Build Coastguard Worker #include <err.h>
28*344aa361SAndroid Build Coastguard Worker #include <kernel/vm.h>
29*344aa361SAndroid Build Coastguard Worker #include <lib/dtb_service/dtb_service.h>
30*344aa361SAndroid Build Coastguard Worker #include <lib/ktipc/ktipc.h>
31*344aa361SAndroid Build Coastguard Worker #if ENABLE_KERNEL_BINDER
32*344aa361SAndroid Build Coastguard Worker #include <lib/shared/binder_discover/binder_discover.h>
33*344aa361SAndroid Build Coastguard Worker #include <lib/shared/device_tree/service/device_tree_service.h>
34*344aa361SAndroid Build Coastguard Worker #endif
35*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/ipc.h>
36*344aa361SAndroid Build Coastguard Worker #include <lib/vmm_obj_service/vmm_obj_service.h>
37*344aa361SAndroid Build Coastguard Worker #include <libfdt.h>
38*344aa361SAndroid Build Coastguard Worker #include <lk/trace.h>
39*344aa361SAndroid Build Coastguard Worker #include <string.h>
40*344aa361SAndroid Build Coastguard Worker 
41*344aa361SAndroid Build Coastguard Worker #define LOCAL_TRACE (0)
42*344aa361SAndroid Build Coastguard Worker 
43*344aa361SAndroid Build Coastguard Worker /* UUID: 185b4dbc-8935-4a1e-89ee-df027b89bc7a */
44*344aa361SAndroid Build Coastguard Worker const static struct uuid device_tree_service_uuid = {
45*344aa361SAndroid Build Coastguard Worker         0x185b4dbc,
46*344aa361SAndroid Build Coastguard Worker         0x8935,
47*344aa361SAndroid Build Coastguard Worker         0x4a1e,
48*344aa361SAndroid Build Coastguard Worker         {0x89, 0xee, 0xdf, 0x02, 0x7b, 0x89, 0xbc, 0x7a},
49*344aa361SAndroid Build Coastguard Worker };
50*344aa361SAndroid Build Coastguard Worker 
51*344aa361SAndroid Build Coastguard Worker const static struct uuid* dtb_service_uuids[] = {
52*344aa361SAndroid Build Coastguard Worker         &device_tree_service_uuid,
53*344aa361SAndroid Build Coastguard Worker };
54*344aa361SAndroid Build Coastguard Worker 
55*344aa361SAndroid Build Coastguard Worker const static struct ktipc_port_acl dtb_service_port_acl = {
56*344aa361SAndroid Build Coastguard Worker         .flags = IPC_PORT_ALLOW_TA_CONNECT,
57*344aa361SAndroid Build Coastguard Worker         .uuid_num = countof(dtb_service_uuids),
58*344aa361SAndroid Build Coastguard Worker         .uuids = dtb_service_uuids,
59*344aa361SAndroid Build Coastguard Worker         .extra_data = NULL,
60*344aa361SAndroid Build Coastguard Worker };
61*344aa361SAndroid Build Coastguard Worker 
dtb_service_add_user(const void * dtb,size_t dtb_size,const char * dtb_port,struct ktipc_server * server)62*344aa361SAndroid Build Coastguard Worker static int dtb_service_add_user(const void* dtb,
63*344aa361SAndroid Build Coastguard Worker                                 size_t dtb_size,
64*344aa361SAndroid Build Coastguard Worker                                 const char* dtb_port,
65*344aa361SAndroid Build Coastguard Worker                                 struct ktipc_server* server) {
66*344aa361SAndroid Build Coastguard Worker     int rc;
67*344aa361SAndroid Build Coastguard Worker     vmm_aspace_t* kas = vmm_get_kernel_aspace();
68*344aa361SAndroid Build Coastguard Worker     struct vmm_obj_slice slice = VMM_OBJ_SLICE_INITIAL_VALUE(slice);
69*344aa361SAndroid Build Coastguard Worker 
70*344aa361SAndroid Build Coastguard Worker     uint64_t aligned_size = round_up(dtb_size, PAGE_SIZE);
71*344aa361SAndroid Build Coastguard Worker     void* dtb_copy;
72*344aa361SAndroid Build Coastguard Worker     rc = vmm_alloc(kas, "dtb copy", aligned_size, &dtb_copy, PAGE_SIZE_SHIFT, 0,
73*344aa361SAndroid Build Coastguard Worker                    ARCH_MMU_FLAG_PERM_NO_EXECUTE);
74*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
75*344aa361SAndroid Build Coastguard Worker         TRACEF("error allocating memory (%d)\n", rc);
76*344aa361SAndroid Build Coastguard Worker         goto err_alloc;
77*344aa361SAndroid Build Coastguard Worker     }
78*344aa361SAndroid Build Coastguard Worker 
79*344aa361SAndroid Build Coastguard Worker     /*
80*344aa361SAndroid Build Coastguard Worker      * We need to make a copy because calling memref_create_from_aspace
81*344aa361SAndroid Build Coastguard Worker      * directly on dtb returns ERR_OUT_OF_RANGE because there is no backing
82*344aa361SAndroid Build Coastguard Worker      * vmm_obj for the kernel image
83*344aa361SAndroid Build Coastguard Worker      */
84*344aa361SAndroid Build Coastguard Worker     rc = fdt_move(dtb, dtb_copy, aligned_size);
85*344aa361SAndroid Build Coastguard Worker     if (rc) {
86*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) to move fdt\n", rc);
87*344aa361SAndroid Build Coastguard Worker         goto err_fdt_move;
88*344aa361SAndroid Build Coastguard Worker     }
89*344aa361SAndroid Build Coastguard Worker 
90*344aa361SAndroid Build Coastguard Worker     rc = vmm_get_obj(kas, (vaddr_t)dtb_copy, aligned_size, &slice);
91*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
92*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) to get vmm_obj\n", rc);
93*344aa361SAndroid Build Coastguard Worker         goto err_get_obj;
94*344aa361SAndroid Build Coastguard Worker     }
95*344aa361SAndroid Build Coastguard Worker 
96*344aa361SAndroid Build Coastguard Worker     struct vmm_obj_service* srv;
97*344aa361SAndroid Build Coastguard Worker     rc = vmm_obj_service_create_ro(dtb_port, &dtb_service_port_acl, slice.obj,
98*344aa361SAndroid Build Coastguard Worker                                    slice.offset, slice.size, &srv);
99*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
100*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) to create vmm_obj_service\n", rc);
101*344aa361SAndroid Build Coastguard Worker         goto err_create_service;
102*344aa361SAndroid Build Coastguard Worker     }
103*344aa361SAndroid Build Coastguard Worker 
104*344aa361SAndroid Build Coastguard Worker     rc = vmm_obj_service_add(srv, server);
105*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
106*344aa361SAndroid Build Coastguard Worker         TRACEF("error (%d) adding new service\n", rc);
107*344aa361SAndroid Build Coastguard Worker         goto err_add_service;
108*344aa361SAndroid Build Coastguard Worker     }
109*344aa361SAndroid Build Coastguard Worker 
110*344aa361SAndroid Build Coastguard Worker     /* vmm_obj_service_create_ro incremented the reference count of slice.obj */
111*344aa361SAndroid Build Coastguard Worker     vmm_obj_slice_release(&slice);
112*344aa361SAndroid Build Coastguard Worker     /* We can free the allocation now that we have the slice */
113*344aa361SAndroid Build Coastguard Worker     vmm_free_region(kas, (vaddr_t)dtb_copy);
114*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
115*344aa361SAndroid Build Coastguard Worker 
116*344aa361SAndroid Build Coastguard Worker err_add_service:
117*344aa361SAndroid Build Coastguard Worker     vmm_obj_service_destroy(&srv);
118*344aa361SAndroid Build Coastguard Worker err_create_service:
119*344aa361SAndroid Build Coastguard Worker     vmm_obj_slice_release(&slice);
120*344aa361SAndroid Build Coastguard Worker err_get_obj:
121*344aa361SAndroid Build Coastguard Worker err_fdt_move:
122*344aa361SAndroid Build Coastguard Worker     vmm_free_region(kas, (vaddr_t)dtb_copy);
123*344aa361SAndroid Build Coastguard Worker err_alloc:
124*344aa361SAndroid Build Coastguard Worker     return rc;
125*344aa361SAndroid Build Coastguard Worker }
126*344aa361SAndroid Build Coastguard Worker 
dtb_service_add(const void * dtb,size_t dtb_size,const char * dt_port,const char * dtb_port,struct ktipc_server * server)127*344aa361SAndroid Build Coastguard Worker int dtb_service_add(const void* dtb,
128*344aa361SAndroid Build Coastguard Worker                     size_t dtb_size,
129*344aa361SAndroid Build Coastguard Worker                     const char* dt_port,
130*344aa361SAndroid Build Coastguard Worker                     const char* dtb_port,
131*344aa361SAndroid Build Coastguard Worker                     struct ktipc_server* server) {
132*344aa361SAndroid Build Coastguard Worker     if (!dtb) {
133*344aa361SAndroid Build Coastguard Worker         TRACEF("invalid dtb pointer\n");
134*344aa361SAndroid Build Coastguard Worker         return ERR_INVALID_ARGS;
135*344aa361SAndroid Build Coastguard Worker     }
136*344aa361SAndroid Build Coastguard Worker     if (!dtb_size) {
137*344aa361SAndroid Build Coastguard Worker         TRACEF("invalid dtb size\n");
138*344aa361SAndroid Build Coastguard Worker         return ERR_INVALID_ARGS;
139*344aa361SAndroid Build Coastguard Worker     }
140*344aa361SAndroid Build Coastguard Worker     if (fdt_check_full(dtb, dtb_size)) {
141*344aa361SAndroid Build Coastguard Worker         TRACEF("invalid dtb contents");
142*344aa361SAndroid Build Coastguard Worker         return ERR_INVALID_ARGS;
143*344aa361SAndroid Build Coastguard Worker     }
144*344aa361SAndroid Build Coastguard Worker     if (!dt_port) {
145*344aa361SAndroid Build Coastguard Worker         TRACEF("invalid kernel port name\n");
146*344aa361SAndroid Build Coastguard Worker         return ERR_INVALID_ARGS;
147*344aa361SAndroid Build Coastguard Worker     }
148*344aa361SAndroid Build Coastguard Worker     if (!dtb_port) {
149*344aa361SAndroid Build Coastguard Worker         TRACEF("invalid user port name\n");
150*344aa361SAndroid Build Coastguard Worker         return ERR_INVALID_ARGS;
151*344aa361SAndroid Build Coastguard Worker     }
152*344aa361SAndroid Build Coastguard Worker     if (!server) {
153*344aa361SAndroid Build Coastguard Worker         TRACEF("invalid server pointer\n");
154*344aa361SAndroid Build Coastguard Worker         return ERR_INVALID_ARGS;
155*344aa361SAndroid Build Coastguard Worker     }
156*344aa361SAndroid Build Coastguard Worker 
157*344aa361SAndroid Build Coastguard Worker #if ENABLE_KERNEL_BINDER
158*344aa361SAndroid Build Coastguard Worker     auto dt = android::sp<com::android::trusty::device_tree::DeviceTree>::make(
159*344aa361SAndroid Build Coastguard Worker             static_cast<const unsigned char*>(dtb), dtb_size);
160*344aa361SAndroid Build Coastguard Worker     int err = binder_discover_add_service(dt_port, dt);
161*344aa361SAndroid Build Coastguard Worker     if (err != android::OK) {
162*344aa361SAndroid Build Coastguard Worker         TRACEF("error adding service (%d)\n", err);
163*344aa361SAndroid Build Coastguard Worker         return ERR_GENERIC;
164*344aa361SAndroid Build Coastguard Worker     }
165*344aa361SAndroid Build Coastguard Worker #endif
166*344aa361SAndroid Build Coastguard Worker 
167*344aa361SAndroid Build Coastguard Worker     int rc = dtb_service_add_user(dtb, dtb_size, dtb_port, server);
168*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
169*344aa361SAndroid Build Coastguard Worker #if ENABLE_KERNEL_BINDER
170*344aa361SAndroid Build Coastguard Worker         binder_discover_remove_service(dt_port);
171*344aa361SAndroid Build Coastguard Worker #endif
172*344aa361SAndroid Build Coastguard Worker         return rc;
173*344aa361SAndroid Build Coastguard Worker     }
174*344aa361SAndroid Build Coastguard Worker 
175*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
176*344aa361SAndroid Build Coastguard Worker }
177