xref: /aosp_15_r20/trusty/kernel/platform/generic-arm64/dtb.c (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 #include <lib/dtb_embedded/dtb_embedded.h>
25*344aa361SAndroid Build Coastguard Worker #include <lib/dtb_service/dtb_service.h>
26*344aa361SAndroid Build Coastguard Worker #include <lib/ktipc/ktipc.h>
27*344aa361SAndroid Build Coastguard Worker #include <libfdt.h>
28*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
29*344aa361SAndroid Build Coastguard Worker #include <lk/trace.h>
30*344aa361SAndroid Build Coastguard Worker #include <uapi/uapi/err.h>
31*344aa361SAndroid Build Coastguard Worker 
32*344aa361SAndroid Build Coastguard Worker #define DT_PORT "com.android.kernel.device_tree"
33*344aa361SAndroid Build Coastguard Worker #define DTB_PORT "com.android.trusty.kernel.device_tree.blob"
34*344aa361SAndroid Build Coastguard Worker 
35*344aa361SAndroid Build Coastguard Worker static struct ktipc_server dtb_ktipc_server =
36*344aa361SAndroid Build Coastguard Worker         KTIPC_SERVER_INITIAL_VALUE(dtb_ktipc_server, "dtb_ktipc_server");
37*344aa361SAndroid Build Coastguard Worker 
find_dtb_by_compatible(const char * compat,const void ** dtb,size_t * dtb_size)38*344aa361SAndroid Build Coastguard Worker static int find_dtb_by_compatible(const char* compat,
39*344aa361SAndroid Build Coastguard Worker                                   const void** dtb,
40*344aa361SAndroid Build Coastguard Worker                                   size_t* dtb_size) {
41*344aa361SAndroid Build Coastguard Worker     assert(dtb);
42*344aa361SAndroid Build Coastguard Worker     assert(dtb_size);
43*344aa361SAndroid Build Coastguard Worker 
44*344aa361SAndroid Build Coastguard Worker     int rc;
45*344aa361SAndroid Build Coastguard Worker     const void* current_dtb = NULL;
46*344aa361SAndroid Build Coastguard Worker     size_t current_dtb_size = 0;
47*344aa361SAndroid Build Coastguard Worker     struct dtb_embedded_iterator* iter;
48*344aa361SAndroid Build Coastguard Worker     rc = dtb_embedded_iterator_new(&iter);
49*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
50*344aa361SAndroid Build Coastguard Worker         return rc;
51*344aa361SAndroid Build Coastguard Worker     }
52*344aa361SAndroid Build Coastguard Worker 
53*344aa361SAndroid Build Coastguard Worker     for (;;) {
54*344aa361SAndroid Build Coastguard Worker         rc = dtb_embedded_iterator_next(iter, &current_dtb, &current_dtb_size);
55*344aa361SAndroid Build Coastguard Worker         if (rc != NO_ERROR) {
56*344aa361SAndroid Build Coastguard Worker             break;
57*344aa361SAndroid Build Coastguard Worker         }
58*344aa361SAndroid Build Coastguard Worker         int test_node_offset = fdt_node_offset_by_compatible(
59*344aa361SAndroid Build Coastguard Worker                 current_dtb, -1 /* search from the start of the dtb */, compat);
60*344aa361SAndroid Build Coastguard Worker         if (test_node_offset >= 0) {
61*344aa361SAndroid Build Coastguard Worker             /* Found the test node */
62*344aa361SAndroid Build Coastguard Worker             *dtb = current_dtb;
63*344aa361SAndroid Build Coastguard Worker             *dtb_size = current_dtb_size;
64*344aa361SAndroid Build Coastguard Worker             break;
65*344aa361SAndroid Build Coastguard Worker         }
66*344aa361SAndroid Build Coastguard Worker     }
67*344aa361SAndroid Build Coastguard Worker 
68*344aa361SAndroid Build Coastguard Worker     dtb_embedded_iterator_free(&iter);
69*344aa361SAndroid Build Coastguard Worker 
70*344aa361SAndroid Build Coastguard Worker     return rc;
71*344aa361SAndroid Build Coastguard Worker }
72*344aa361SAndroid Build Coastguard Worker 
apply_test_overlay(const void * base_dtb,size_t base_dtb_size,const void * test_dtbo,size_t test_dtbo_size)73*344aa361SAndroid Build Coastguard Worker static void* apply_test_overlay(const void* base_dtb,
74*344aa361SAndroid Build Coastguard Worker                                 size_t base_dtb_size,
75*344aa361SAndroid Build Coastguard Worker                                 const void* test_dtbo,
76*344aa361SAndroid Build Coastguard Worker                                 size_t test_dtbo_size) {
77*344aa361SAndroid Build Coastguard Worker     /* Overestimate the size needed for the full dtb for now */
78*344aa361SAndroid Build Coastguard Worker     size_t full_size = base_dtb_size + test_dtbo_size;
79*344aa361SAndroid Build Coastguard Worker     void* base = calloc(1, full_size);
80*344aa361SAndroid Build Coastguard Worker     if (!base) {
81*344aa361SAndroid Build Coastguard Worker         goto alloc_base;
82*344aa361SAndroid Build Coastguard Worker     }
83*344aa361SAndroid Build Coastguard Worker     /*
84*344aa361SAndroid Build Coastguard Worker      * libfdt overwrites part of the dtbo header if applying the overlay fails
85*344aa361SAndroid Build Coastguard Worker      * so we have to make a temporary copy since the original dtbo is in
86*344aa361SAndroid Build Coastguard Worker      * read-only memory.
87*344aa361SAndroid Build Coastguard Worker      */
88*344aa361SAndroid Build Coastguard Worker     void* overlay = calloc(1, test_dtbo_size);
89*344aa361SAndroid Build Coastguard Worker     if (!overlay) {
90*344aa361SAndroid Build Coastguard Worker         goto alloc_overlay;
91*344aa361SAndroid Build Coastguard Worker     }
92*344aa361SAndroid Build Coastguard Worker     /*
93*344aa361SAndroid Build Coastguard Worker      * Using fdt_open_into copies the dtb to the buffer allocated above and
94*344aa361SAndroid Build Coastguard Worker      * updates the fdt header with the new buffer size
95*344aa361SAndroid Build Coastguard Worker      */
96*344aa361SAndroid Build Coastguard Worker     int rc = fdt_open_into(base_dtb, base, full_size);
97*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
98*344aa361SAndroid Build Coastguard Worker         TRACEF("fdt_open_into failed for base dtb (%d)\n", rc);
99*344aa361SAndroid Build Coastguard Worker         goto copy_base;
100*344aa361SAndroid Build Coastguard Worker     }
101*344aa361SAndroid Build Coastguard Worker     rc = fdt_open_into(test_dtbo, overlay, test_dtbo_size);
102*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
103*344aa361SAndroid Build Coastguard Worker         TRACEF("fdt_open_into failed for test dtb overlay (%d)\n", rc);
104*344aa361SAndroid Build Coastguard Worker         goto copy_overlay;
105*344aa361SAndroid Build Coastguard Worker     }
106*344aa361SAndroid Build Coastguard Worker     rc = fdt_overlay_apply(base, overlay);
107*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
108*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to apply test overlay to base dtb (%d)\n", rc);
109*344aa361SAndroid Build Coastguard Worker         goto apply_overlay;
110*344aa361SAndroid Build Coastguard Worker     }
111*344aa361SAndroid Build Coastguard Worker     free(overlay);
112*344aa361SAndroid Build Coastguard Worker     return base;
113*344aa361SAndroid Build Coastguard Worker 
114*344aa361SAndroid Build Coastguard Worker apply_overlay:
115*344aa361SAndroid Build Coastguard Worker copy_overlay:
116*344aa361SAndroid Build Coastguard Worker copy_base:
117*344aa361SAndroid Build Coastguard Worker     free(overlay);
118*344aa361SAndroid Build Coastguard Worker alloc_overlay:
119*344aa361SAndroid Build Coastguard Worker     free(base);
120*344aa361SAndroid Build Coastguard Worker alloc_base:
121*344aa361SAndroid Build Coastguard Worker     return NULL;
122*344aa361SAndroid Build Coastguard Worker }
123*344aa361SAndroid Build Coastguard Worker 
platform_dtb_init(uint level)124*344aa361SAndroid Build Coastguard Worker static void platform_dtb_init(uint level) {
125*344aa361SAndroid Build Coastguard Worker     int rc;
126*344aa361SAndroid Build Coastguard Worker     rc = ktipc_server_start(&dtb_ktipc_server);
127*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
128*344aa361SAndroid Build Coastguard Worker         panic("Failed (%d) to start dtb server\n", rc);
129*344aa361SAndroid Build Coastguard Worker     }
130*344aa361SAndroid Build Coastguard Worker 
131*344aa361SAndroid Build Coastguard Worker     const void* base_dtb = NULL;
132*344aa361SAndroid Build Coastguard Worker     const void* test_dtbo = NULL;
133*344aa361SAndroid Build Coastguard Worker     size_t base_dtb_size, test_dtbo_size = 0;
134*344aa361SAndroid Build Coastguard Worker     rc = find_dtb_by_compatible("google,test_base", &base_dtb, &base_dtb_size);
135*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
136*344aa361SAndroid Build Coastguard Worker         panic("No embedded base dtb found (%d)\n", rc);
137*344aa361SAndroid Build Coastguard Worker     }
138*344aa361SAndroid Build Coastguard Worker 
139*344aa361SAndroid Build Coastguard Worker     rc = find_dtb_by_compatible("google,test_overlay", &test_dtbo,
140*344aa361SAndroid Build Coastguard Worker                                 &test_dtbo_size);
141*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
142*344aa361SAndroid Build Coastguard Worker         panic("No embedded test dtbo found (%d)\n", rc);
143*344aa361SAndroid Build Coastguard Worker     }
144*344aa361SAndroid Build Coastguard Worker 
145*344aa361SAndroid Build Coastguard Worker     const void* dtb = apply_test_overlay(base_dtb, base_dtb_size, test_dtbo,
146*344aa361SAndroid Build Coastguard Worker                                          test_dtbo_size);
147*344aa361SAndroid Build Coastguard Worker     if (!dtb) {
148*344aa361SAndroid Build Coastguard Worker         panic("Failed to apply test overlay to base dtb\n");
149*344aa361SAndroid Build Coastguard Worker     }
150*344aa361SAndroid Build Coastguard Worker     size_t dtb_size = fdt_totalsize(dtb);
151*344aa361SAndroid Build Coastguard Worker 
152*344aa361SAndroid Build Coastguard Worker     rc = dtb_service_add(dtb, dtb_size, DT_PORT, DTB_PORT, &dtb_ktipc_server);
153*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
154*344aa361SAndroid Build Coastguard Worker         panic("Failed (%d) to add dtb service to server\n", rc);
155*344aa361SAndroid Build Coastguard Worker     }
156*344aa361SAndroid Build Coastguard Worker }
157*344aa361SAndroid Build Coastguard Worker 
158*344aa361SAndroid Build Coastguard Worker LK_INIT_HOOK(platform_dtb, platform_dtb_init, LK_INIT_LEVEL_THREADING + 1);
159