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, ¤t_dtb, ¤t_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