xref: /aosp_15_r20/trusty/kernel/lib/dtb_embedded/dtb_embedded.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 <inttypes.h>
25*344aa361SAndroid Build Coastguard Worker #include <lib/dtb_embedded/dtb_embedded.h>
26*344aa361SAndroid Build Coastguard Worker #include <libfdt.h>
27*344aa361SAndroid Build Coastguard Worker #include <lk/compiler.h>
28*344aa361SAndroid Build Coastguard Worker #include <lk/macros.h>
29*344aa361SAndroid Build Coastguard Worker #include <lk/trace.h>
30*344aa361SAndroid Build Coastguard Worker #include <stdint.h>
31*344aa361SAndroid Build Coastguard Worker #include <uapi/uapi/err.h>
32*344aa361SAndroid Build Coastguard Worker 
33*344aa361SAndroid Build Coastguard Worker #define LOCAL_TRACE (0)
34*344aa361SAndroid Build Coastguard Worker 
35*344aa361SAndroid Build Coastguard Worker extern char __trusty_dtb_start;
36*344aa361SAndroid Build Coastguard Worker extern char __trusty_dtb_end;
37*344aa361SAndroid Build Coastguard Worker 
38*344aa361SAndroid Build Coastguard Worker struct dtb_embedded_iterator {
39*344aa361SAndroid Build Coastguard Worker     uintptr_t offset;
40*344aa361SAndroid Build Coastguard Worker };
41*344aa361SAndroid Build Coastguard Worker 
dtb_embedded_iterator_reset(struct dtb_embedded_iterator * iter)42*344aa361SAndroid Build Coastguard Worker void dtb_embedded_iterator_reset(struct dtb_embedded_iterator* iter) {
43*344aa361SAndroid Build Coastguard Worker     if (iter) {
44*344aa361SAndroid Build Coastguard Worker         iter->offset = 0;
45*344aa361SAndroid Build Coastguard Worker     }
46*344aa361SAndroid Build Coastguard Worker }
47*344aa361SAndroid Build Coastguard Worker 
dtb_embedded_iterator_new(struct dtb_embedded_iterator ** piter)48*344aa361SAndroid Build Coastguard Worker int dtb_embedded_iterator_new(struct dtb_embedded_iterator** piter) {
49*344aa361SAndroid Build Coastguard Worker     ASSERT(piter);
50*344aa361SAndroid Build Coastguard Worker 
51*344aa361SAndroid Build Coastguard Worker     struct dtb_embedded_iterator* iter = (struct dtb_embedded_iterator*)calloc(
52*344aa361SAndroid Build Coastguard Worker             1, sizeof(struct dtb_embedded_iterator));
53*344aa361SAndroid Build Coastguard Worker     if (!iter) {
54*344aa361SAndroid Build Coastguard Worker         TRACEF("failed to allocate iterator\n");
55*344aa361SAndroid Build Coastguard Worker         return ERR_NO_MEMORY;
56*344aa361SAndroid Build Coastguard Worker     }
57*344aa361SAndroid Build Coastguard Worker 
58*344aa361SAndroid Build Coastguard Worker     dtb_embedded_iterator_reset(iter);
59*344aa361SAndroid Build Coastguard Worker     *piter = iter;
60*344aa361SAndroid Build Coastguard Worker 
61*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
62*344aa361SAndroid Build Coastguard Worker }
63*344aa361SAndroid Build Coastguard Worker 
dtb_embedded_iterator_free(struct dtb_embedded_iterator ** piter)64*344aa361SAndroid Build Coastguard Worker void dtb_embedded_iterator_free(struct dtb_embedded_iterator** piter) {
65*344aa361SAndroid Build Coastguard Worker     ASSERT(piter);
66*344aa361SAndroid Build Coastguard Worker 
67*344aa361SAndroid Build Coastguard Worker     if (*piter) {
68*344aa361SAndroid Build Coastguard Worker         free(*piter);
69*344aa361SAndroid Build Coastguard Worker         *piter = NULL;
70*344aa361SAndroid Build Coastguard Worker     }
71*344aa361SAndroid Build Coastguard Worker }
72*344aa361SAndroid Build Coastguard Worker 
dtb_embedded_iterator_next(struct dtb_embedded_iterator * iter,const void ** dtb,size_t * dtb_size)73*344aa361SAndroid Build Coastguard Worker int dtb_embedded_iterator_next(struct dtb_embedded_iterator* iter,
74*344aa361SAndroid Build Coastguard Worker                                const void** dtb,
75*344aa361SAndroid Build Coastguard Worker                                size_t* dtb_size) {
76*344aa361SAndroid Build Coastguard Worker     if (!iter) {
77*344aa361SAndroid Build Coastguard Worker         TRACEF("Invalid iterator\n");
78*344aa361SAndroid Build Coastguard Worker         return ERR_INVALID_ARGS;
79*344aa361SAndroid Build Coastguard Worker     }
80*344aa361SAndroid Build Coastguard Worker     if (!dtb) {
81*344aa361SAndroid Build Coastguard Worker         TRACEF("Invalid dtb pointer\n");
82*344aa361SAndroid Build Coastguard Worker         return ERR_INVALID_ARGS;
83*344aa361SAndroid Build Coastguard Worker     }
84*344aa361SAndroid Build Coastguard Worker     if (!dtb_size) {
85*344aa361SAndroid Build Coastguard Worker         TRACEF("Invalid dtb size pointer\n");
86*344aa361SAndroid Build Coastguard Worker         return ERR_INVALID_ARGS;
87*344aa361SAndroid Build Coastguard Worker     }
88*344aa361SAndroid Build Coastguard Worker 
89*344aa361SAndroid Build Coastguard Worker     /* Check that the iterator is within the embedded dtb range */
90*344aa361SAndroid Build Coastguard Worker     uintptr_t end = (uintptr_t)&__trusty_dtb_end;
91*344aa361SAndroid Build Coastguard Worker     uintptr_t start = (uintptr_t)&__trusty_dtb_start;
92*344aa361SAndroid Build Coastguard Worker     uintptr_t total_size = end - start;
93*344aa361SAndroid Build Coastguard Worker     if (iter->offset >= total_size) {
94*344aa361SAndroid Build Coastguard Worker         TRACEF("Embedded dtb iterator at offset %" PRIuPTR "out of range\n",
95*344aa361SAndroid Build Coastguard Worker                iter->offset);
96*344aa361SAndroid Build Coastguard Worker         return ERR_OUT_OF_RANGE;
97*344aa361SAndroid Build Coastguard Worker     }
98*344aa361SAndroid Build Coastguard Worker 
99*344aa361SAndroid Build Coastguard Worker     /* Validate the header of the next dtb */
100*344aa361SAndroid Build Coastguard Worker     const void* dtb_start = (const void*)(start + iter->offset);
101*344aa361SAndroid Build Coastguard Worker     int rc = fdt_check_header(dtb_start);
102*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
103*344aa361SAndroid Build Coastguard Worker         TRACEF("Embedded dtb at offset %" PRIuPTR
104*344aa361SAndroid Build Coastguard Worker                " has an invalid header (%d)\n",
105*344aa361SAndroid Build Coastguard Worker                iter->offset, rc);
106*344aa361SAndroid Build Coastguard Worker         return ERR_BAD_STATE;
107*344aa361SAndroid Build Coastguard Worker     }
108*344aa361SAndroid Build Coastguard Worker 
109*344aa361SAndroid Build Coastguard Worker     /*
110*344aa361SAndroid Build Coastguard Worker      * Check that the dtb size is in the expected range. Each dtb's size is read
111*344aa361SAndroid Build Coastguard Worker      * from its header plus 4 bytes from the symbol size inserted by
112*344aa361SAndroid Build Coastguard Worker      * INCBIN_ALIGNED. Then we round up to 8 bytes since each individual dtb is
113*344aa361SAndroid Build Coastguard Worker      * 8-byte aligned.
114*344aa361SAndroid Build Coastguard Worker      */
115*344aa361SAndroid Build Coastguard Worker     const size_t dtb_alignment = 8;
116*344aa361SAndroid Build Coastguard Worker     const size_t sym_size = 4;
117*344aa361SAndroid Build Coastguard Worker     size_t next_dtb_size =
118*344aa361SAndroid Build Coastguard Worker             round_up(fdt_totalsize(dtb_start) + sym_size, dtb_alignment);
119*344aa361SAndroid Build Coastguard Worker     if (next_dtb_size + iter->offset > total_size) {
120*344aa361SAndroid Build Coastguard Worker         TRACEF("Embedded dtb at offset %" PRIuPTR " has invalid size %zu\n",
121*344aa361SAndroid Build Coastguard Worker                iter->offset, next_dtb_size);
122*344aa361SAndroid Build Coastguard Worker         return ERR_BAD_LEN;
123*344aa361SAndroid Build Coastguard Worker     }
124*344aa361SAndroid Build Coastguard Worker     iter->offset += next_dtb_size;
125*344aa361SAndroid Build Coastguard Worker     *dtb = dtb_start;
126*344aa361SAndroid Build Coastguard Worker     *dtb_size = next_dtb_size;
127*344aa361SAndroid Build Coastguard Worker     LTRACEF("Found embedded dtb at offset %" PRIuPTR "\n", iter->offset);
128*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
129*344aa361SAndroid Build Coastguard Worker }
130