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