Coverage Report

Created: 2026-10-17 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/barebox/pbl/handoff-data.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0
2
#include <common.h>
3
#include <pbl/handoff-data.h>
4
#include <init.h>
5
#include <linux/list.h>
6
#include <memory.h>
7
#include <fdt.h>
8
#include <compressed-dtb.h>
9
10
static struct handoff_data *handoff_data = (void *)-1;
11
12
static struct handoff_data *handoff_data_get(void)
13
52
{
14
52
  static struct handoff_data __handoff_data __section(.data);
15
16
  /*
17
   * Sometimes the PBL copies itself to some other location and is
18
   * re-entered at that location. For example on some i.MX SoCs we have
19
   * to move the PBL out of the SRAM (which will be occupied by the TF-A
20
   * later). We force the handoff_data variable into the data segment.
21
   * When moving the PBL somewhere else with handoff_data set we move the
22
   * content of the variable with it and thus find it to have the correct
23
   * value in the new PBL.
24
   */
25
52
  if (handoff_data == (void *)-1) {
26
52
    handoff_data = &__handoff_data;
27
52
    INIT_LIST_HEAD(&handoff_data->entries);
28
52
  }
29
30
52
  return handoff_data;
31
52
}
32
33
/**
34
 * handoff_data_set - set the handoff data to be at a specified pointer
35
 * @handoff: the place where the handoff data is
36
 *
37
 * This sets the handoff data to @handoff. To be used by barebox proper
38
 * to pass the place where the handoff data has been placed by the PBL.
39
 */
40
void handoff_data_set(struct handoff_data *handoff)
41
0
{
42
0
  handoff_data = handoff;
43
0
}
44
45
/**
46
 * handoff_data_add_entry - add a new handoff data entry
47
 * @hde: the new entry
48
 *
49
 * This adds a new handoff data entry.
50
 */
51
void handoff_data_add_entry(struct handoff_data_entry *hde)
52
0
{
53
0
  struct handoff_data *hd = handoff_data_get();
54
55
0
  list_add_tail(&hde->list, &hd->entries);
56
0
}
57
58
/**
59
 * handoff_data_size - calculate the handoff data size
60
 *
61
 * This calculates the size needed for the current handoff data
62
 * when put to a contiguous memory regions. Can be used to get the
63
 * size needed in preparation for a handoff_data_move()
64
 */
65
size_t __handoff_data_size(const struct handoff_data *hd)
66
0
{
67
0
  struct handoff_data_entry *hde;
68
0
  size_t size = 0;
69
0
  size_t dsize = 0;
70
71
0
  if (!hd)
72
0
    hd = handoff_data_get();
73
74
0
  dsize += sizeof(*hd);
75
76
0
  list_for_each_entry(hde, &hd->entries, list) {
77
0
    dsize += sizeof(*hde);
78
0
    size += ALIGN(hde->size, 8);
79
0
  }
80
81
0
  return dsize + size;
82
0
}
83
84
/**
85
 * handoff_data_move - move handoff data to specified destination
86
 * @dest: The place where to move the handoff data to
87
 *
88
 * This moves the handoff data to @dest and also sets the new location
89
 * to @dest. This can be used to move the handoff data to a contiguous
90
 * region outside the binary. Note once moved no data should be added,
91
 * as that would make the handoff_data discontigoous again.
92
 */
93
void handoff_data_move(void *dest)
94
0
{
95
0
  struct handoff_data *hd = handoff_data_get();
96
0
  struct handoff_data *hdnew = dest;
97
0
  struct handoff_data_entry *hde;
98
99
0
  INIT_LIST_HEAD(&hdnew->entries);
100
101
0
  dest = hdnew + 1;
102
103
0
  list_for_each_entry(hde, &hd->entries, list) {
104
0
    struct handoff_data_entry *newde = dest;
105
106
0
    dest = newde + 1;
107
108
0
    if (hde->flags & HANDOFF_DATA_FLAG_NO_COPY) {
109
0
      newde->data = hde->data;
110
0
    } else {
111
0
      memcpy(dest, hde->data, hde->size);
112
0
      newde->data = dest;
113
0
      dest += ALIGN(hde->size, 8);
114
0
    }
115
116
0
    newde->size = hde->size;
117
0
    newde->cookie = hde->cookie;
118
0
    newde->flags = hde->flags;
119
0
    list_add_tail(&newde->list, &hdnew->entries);
120
0
  }
121
122
0
  handoff_data_set(hdnew);
123
0
}
124
125
/**
126
 * handoff_data_get_entry - get the memory associated to a cookie
127
 * @cookie: the cookie the data is identified with
128
 * @size: size of the memory returned
129
 *
130
 * This returns the memory associated with @cookie.
131
 */
132
void *handoff_data_get_entry(unsigned int cookie, size_t *size)
133
0
{
134
0
  struct handoff_data *hd = handoff_data_get();
135
0
  struct handoff_data_entry *hde;
136
137
0
  list_for_each_entry(hde, &hd->entries, list) {
138
0
    if (hde->cookie == cookie) {
139
0
      *size = hde->size;
140
0
      return hde->data;
141
0
    }
142
0
  }
143
144
0
  return NULL;
145
0
}
146
147
/**
148
 * handoff_data_show - show current handoff data entries
149
 *
150
 * This prints the current handoff data entries to the console for debugging
151
 * purposes.
152
 */
153
int handoff_data_show(void)
154
0
{
155
0
  struct handoff_data *hd = handoff_data_get();
156
0
  struct handoff_data_entry *hde;
157
158
0
  list_for_each_entry(hde, &hd->entries, list) {
159
0
    printf("handoff 0x%08x at 0x%p (size %zu)\n",
160
0
      hde->cookie, hde->data, hde->size);
161
0
  }
162
163
0
  return 0;
164
0
}
165
166
void handoff_data_add_dt(void *fdt)
167
0
{
168
0
  if (blob_is_fdt(fdt)) {
169
0
    handoff_data_add(HANDOFF_DATA_INTERNAL_DT, fdt,
170
0
         get_unaligned_be32(fdt + 4));
171
0
  } else if (blob_is_compressed_fdt(fdt)) {
172
0
    struct barebox_boarddata_compressed_dtb *bd = fdt;
173
174
0
    handoff_data_add(HANDOFF_DATA_INTERNAL_DT_Z, fdt,
175
0
         bd->datalen + sizeof(*bd));
176
0
  }
177
0
}
178
179
static const char *handoff_data_entry_name(struct handoff_data_entry *hde)
180
0
{
181
0
  static char name[sizeof("handoff 12345678")];
182
183
0
  switch (hde->cookie) {
184
0
  case HANDOFF_DATA_INTERNAL_DT:
185
0
    return "handoff FDT (internal)";
186
0
  case HANDOFF_DATA_INTERNAL_DT_Z:
187
0
    return "handoff FDT (internal, compressed)";
188
0
  case HANDOFF_DATA_EXTERNAL_DT:
189
0
    return "handoff FDT (external)";
190
0
  case HANDOFF_DATA_ARM_MACHINE:
191
0
    return "ARM machine number";
192
0
  case HANDOFF_DATA_TEE_DT_OVL:
193
0
    return "handoff TEE FDTO";
194
0
  default:
195
0
    sprintf(name, "handoff %08x", hde->cookie);
196
0
    return name;
197
0
  }
198
0
}
199
200
static int handoff_data_reserve(void)
201
52
{
202
52
  struct handoff_data *hd = handoff_data_get();
203
52
  struct handoff_data_entry *hde;
204
205
52
  list_for_each_entry(hde, &hd->entries, list) {
206
0
    const char *name = handoff_data_entry_name(hde);
207
0
    request_barebox_region(name, (resource_size_t)hde->data, hde->size,
208
0
               MEMATTRS_RO);
209
0
  }
210
211
52
  return 0;
212
52
}
213
late_initcall(handoff_data_reserve);