blob: f42b9c036650e2281bef23684c21ca253d482ff7 [file] [log] [blame]
Manish Pandey65fe3642025-03-21 12:44:42 +00001/*
2 * Copyright The Transfer List Library Contributors
3 *
4 * SPDX-License-Identifier: MIT OR GPL-2.0-or-later
5 */
6
7#ifndef TRANSFER_LIST_H
8#define TRANSFER_LIST_H
9
10#include <assert.h>
11#include <stdbool.h>
Harrison Mutaie0bc2c82025-05-08 15:36:08 +000012#include <stddef.h>
Manish Pandey65fe3642025-03-21 12:44:42 +000013#include <stdint.h>
14
15#define TRANSFER_LIST_SIGNATURE 0x4a0fb10b
16#define TRANSFER_LIST_VERSION 0x0001
17
18/*
19 * Init value of maximum alignment required by any TE data in the TL
20 * specified as a power of two
21 */
22#define TRANSFER_LIST_INIT_MAX_ALIGN 3U
23
24/* Alignment required by TE header start address, in bytes */
25#define TRANSFER_LIST_GRANULE 8U
26
27/*
28 * Version of the register convention used.
29 * Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9
30 */
31#define REGISTER_CONVENTION_VERSION_SHIFT_64 32UL
32#define REGISTER_CONVENTION_VERSION_SHIFT_32 24UL
33#define REGISTER_CONVENTION_VERSION_MASK 0xffUL
34#define REGISTER_CONVENTION_VERSION 1UL
35
36#define TRANSFER_LIST_HANDOFF_X1_VALUE(__version) \
37 ((TRANSFER_LIST_SIGNATURE & \
38 ((1UL << REGISTER_CONVENTION_VERSION_SHIFT_64) - 1)) | \
39 (((__version)&REGISTER_CONVENTION_VERSION_MASK) \
40 << REGISTER_CONVENTION_VERSION_SHIFT_64))
41
42#define TRANSFER_LIST_HANDOFF_R1_VALUE(__version) \
43 ((TRANSFER_LIST_SIGNATURE & \
44 ((1UL << REGISTER_CONVENTION_VERSION_SHIFT_32) - 1)) | \
45 (((__version)&REGISTER_CONVENTION_VERSION_MASK) \
46 << REGISTER_CONVENTION_VERSION_SHIFT_32))
47
48#ifndef __ASSEMBLER__
49
50#define TL_FLAGS_HAS_CHECKSUM (1U << 0U)
51
52enum transfer_list_tag_id {
53 TL_TAG_EMPTY = 0,
54 TL_TAG_FDT = 1,
55 TL_TAG_HOB_BLOCK = 2,
56 TL_TAG_HOB_LIST = 3,
57 TL_TAG_ACPI_TABLE_AGGREGATE = 4,
Harrison Mutai1171f832025-03-21 15:33:17 +000058 TL_TAG_TPM_EVLOG = 5,
Manish Pandey65fe3642025-03-21 12:44:42 +000059 TL_TAG_OPTEE_PAGABLE_PART = 0x100,
60 TL_TAG_DT_SPMC_MANIFEST = 0x101,
61 TL_TAG_EXEC_EP_INFO64 = 0x102,
Manish Pandey65fe3642025-03-21 12:44:42 +000062 TL_TAG_SRAM_LAYOUT64 = 0x104,
63 TL_TAG_MBEDTLS_HEAP_INFO = 0x105,
Yeoreum Yune25480f2025-06-02 20:40:23 +010064 TL_TAG_DT_FFA_MANIFEST = 0x106,
Harrison Mutai1171f832025-03-21 15:33:17 +000065 TL_TAG_SRAM_LAYOUT32 = 0x107,
Yeoreum Yune25480f2025-06-02 20:40:23 +010066 TL_TAG_EXEC_EP_INFO32 = 0x108,
Manish Pandey65fe3642025-03-21 12:44:42 +000067};
68
69enum transfer_list_ops {
70 TL_OPS_NON, /* invalid for any operation */
71 TL_OPS_ALL, /* valid for all operations */
72 TL_OPS_RO, /* valid for read only */
73 TL_OPS_CUS, /* abort or switch to special code to interpret */
74};
75
76struct transfer_list_header {
77 uint32_t signature;
78 uint8_t checksum;
79 uint8_t version;
80 uint8_t hdr_size;
81 uint8_t alignment; /* max alignment of TE data */
82 uint32_t size; /* TL header + all TEs */
83 uint32_t max_size;
84 uint32_t flags;
85 uint32_t reserved; /* spare bytes */
86 /*
87 * Commented out element used to visualize dynamic part of the
88 * data structure.
89 *
90 * Note that struct transfer_list_entry also is dynamic in size
91 * so the elements can't be indexed directly but instead must be
92 * traversed in order
93 *
94 * struct transfer_list_entry entries[];
95 */
96};
97
98struct __attribute__((packed)) transfer_list_entry {
99 uint32_t tag_id : 24;
100 uint8_t hdr_size;
101 uint32_t data_size;
102 /*
103 * Commented out element used to visualize dynamic part of the
104 * data structure.
105 *
106 * Note that padding is added at the end of @data to make to reach
107 * a 8-byte boundary.
108 *
109 * uint8_t data[ROUNDUP(data_size, 8)];
110 */
111};
112
Harrison Mutai736f1952025-05-01 08:08:20 +0000113/*
114 * Provide a backward-compatible implementation of static_assert.
115 * This keyword was introduced in C11, so it may be unavailable in
116 * projects targeting older C standards.
117 */
118#if __STDC_VERSION__ >= 201112L
119#define LIBTL_STATIC_ASSERT(cond, msg) _Static_assert(cond, #msg)
120#else
121#define LIBTL_STATIC_ASSERT(cond, msg) \
122 typedef char static_assertion_##msg[(cond) ? 1 : -1]
123#endif
124
125LIBTL_STATIC_ASSERT(sizeof(struct transfer_list_entry) == 0x8U,
126 assert_transfer_list_entry_size);
Manish Pandey65fe3642025-03-21 12:44:42 +0000127
Harrison Mutaib01ab962025-05-01 10:17:58 +0000128/**
129 * Initialize a transfer list in a reserved memory region.
130 *
131 * Sets up an empty transfer list at the specified address. Ensures alignment
132 * and zeroes the region. Compliant to 2.4.5 of Firmware Handoff specification
133 * (v0.9).
134 *
135 * @param[in] addr Pointer to memory to initialize as a transfer list.
136 * @param[in] max_size Total size of the memory region in bytes.
137 *
138 * @return Pointer to the initialized transfer list, or NULL on error.
139 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000140struct transfer_list_header *transfer_list_init(void *addr, size_t max_size);
141
Harrison Mutaib01ab962025-05-01 10:17:58 +0000142/**
143 * Relocate a transfer list to a new memory region.
144 *
145 * Moves an existing transfer list to a new location while preserving alignment
146 * and contents. Updates internal pointers and checksum accordingly. Compliant
147 * to 2.4.6 of Firmware Handoff specification (v0.9).
148 *
149 * @param[in] tl Pointer to the existing transfer list.
150 * @param[in] addr Target address for relocation.
151 * @param[in] max_size Size of the target memory region in bytes.
152 *
153 * @return Pointer to the relocated transfer list, or NULL on error.
154 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000155struct transfer_list_header *
156transfer_list_relocate(struct transfer_list_header *tl, void *addr,
157 size_t max_size);
Harrison Mutaib01ab962025-05-01 10:17:58 +0000158
159/**
160 * Check the validity of a transfer list header.
161 *
162 * Validates signature, size, version, and checksum of a transfer list.
163 * Compliant to 2.4.1 of Firmware Handoff specification (v0.9)
164 *
165 * @param[in] tl Pointer to the transfer list to verify.
166 *
167 * @return A transfer_list_ops code indicating valid operations.
168 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000169enum transfer_list_ops
170transfer_list_check_header(const struct transfer_list_header *tl);
171
Harrison Mutaib01ab962025-05-01 10:17:58 +0000172/**
173 * Get the next transfer entry in the list.
174 *
175 * Enumerates transfer entries starting from the given entry or from the beginning.
176 *
177 * @param[in] tl Pointer to the transfer list.
178 * @param[in] last Pointer to the previous entry, or NULL to start at the beginning.
179 *
180 * @return Pointer to the next valid entry, or NULL on error or end of list.
181 */
182struct transfer_list_entry *
183transfer_list_next(struct transfer_list_header *tl,
184 struct transfer_list_entry *last);
185
186/**
187 * Get the previous transfer entry in the list.
188 *
189 * Enumerates transfer entries backward from the given entry.
190 *
191 * @param[in] tl Pointer to the transfer list.
192 * @param[in] last Pointer to the current entry.
193 *
194 * @return Pointer to the previous valid entry, or NULL on error or start of list.
195 */
196struct transfer_list_entry *
197transfer_list_prev(struct transfer_list_header *tl,
198 struct transfer_list_entry *last);
199
200/**
201 * Update the checksum of a transfer list.
202 *
203 * Recomputes and updates the checksum field based on current contents.
204 *
205 * @param[in,out] tl Pointer to the transfer list to update.
206 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000207void transfer_list_update_checksum(struct transfer_list_header *tl);
Harrison Mutaib01ab962025-05-01 10:17:58 +0000208
209/**
210 * Verify the checksum of a transfer list.
211 *
212 * Computes and checks the checksum against the stored value.
213 *
214 * @param[in] tl Pointer to the transfer list to verify.
215 *
216 * @return true if checksum is valid, false otherwise.
217 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000218bool transfer_list_verify_checksum(const struct transfer_list_header *tl);
219
Harrison Mutaib01ab962025-05-01 10:17:58 +0000220/**
221 * Set the data size of a transfer entry.
222 *
223 * Modifies the data size field of a given entry and adjusts subsequent entries.
224 *
225 * @param[in,out] tl Pointer to the parent transfer list.
226 * @param[in,out] te Pointer to the entry to modify.
227 * @param[in] new_data_size New size of the entry data in bytes.
228 *
229 * @return true on success, false on error.
230 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000231bool transfer_list_set_data_size(struct transfer_list_header *tl,
Harrison Mutaib01ab962025-05-01 10:17:58 +0000232 struct transfer_list_entry *te,
Manish Pandey65fe3642025-03-21 12:44:42 +0000233 uint32_t new_data_size);
234
Harrison Mutaib01ab962025-05-01 10:17:58 +0000235/**
236 * Remove a transfer entry by marking it as empty.
237 *
238 * Clears the tag of a given entry and updates the list checksum.
239 *
240 * @param[in,out] tl Pointer to the transfer list.
241 * @param[in,out] te Pointer to the entry to remove.
242 *
243 * @return true on success, false on error.
244 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000245bool transfer_list_rem(struct transfer_list_header *tl,
Harrison Mutaib01ab962025-05-01 10:17:58 +0000246 struct transfer_list_entry *te);
Manish Pandey65fe3642025-03-21 12:44:42 +0000247
Harrison Mutaib01ab962025-05-01 10:17:58 +0000248/**
249 * Add a new transfer entry to the list.
250 *
251 * Appends a new entry with specified tag and data to the list tail.
252 *
253 * @param[in,out] tl Pointer to the transfer list.
254 * @param[in] tag_id Tag identifier for the new entry.
255 * @param[in] data_size Size of the entry data in bytes.
256 * @param[in] data Pointer to the data to copy (can be NULL).
257 *
258 * @return Pointer to the added entry, or NULL on error.
259 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000260struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl,
261 uint32_t tag_id,
262 uint32_t data_size,
263 const void *data);
264
Harrison Mutaib01ab962025-05-01 10:17:58 +0000265/**
266 * Add a new transfer entry with specific alignment requirements.
267 *
268 * Inserts padding if needed to meet the alignment of the entry data.
269 *
270 * @param[in,out] tl Pointer to the transfer list.
271 * @param[in] tag_id Tag identifier for the new entry.
272 * @param[in] data_size Size of the entry data in bytes.
273 * @param[in] data Pointer to the data to copy (can be NULL).
274 * @param[in] alignment Desired alignment (as log2 value).
275 *
276 * @return Pointer to the added entry, or NULL on error.
277 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000278struct transfer_list_entry *
279transfer_list_add_with_align(struct transfer_list_header *tl, uint32_t tag_id,
280 uint32_t data_size, const void *data,
281 uint8_t alignment);
282
Harrison Mutaib01ab962025-05-01 10:17:58 +0000283/**
284 * Find an entry in the transfer list by tag.
285 *
286 * Search for an existing transfer entry with the specified tag id from a
287 * transfer list
288 *
289 * @param[in] tl Pointer to the transfer list.
290 * @param[in] tag_id Tag identifier to search for.
291 *
292 * @return Pointer to the found entry, or NULL if not found.
293 */
Manish Pandey65fe3642025-03-21 12:44:42 +0000294struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
295 uint32_t tag_id);
296
Harrison Mutaib01ab962025-05-01 10:17:58 +0000297/**
298 * Set handoff arguments in the entry point info structure.
299 *
300 * This function populates the provided entry point info structure with data
301 * from the transfer list.
302 *
303 * @param[in] tl Pointer to the transfer list.
304 * @param[out] ep_info Pointer to the entry point info structure to populate.
305 *
306 * @return Pointer to the populated entry point info structure.
307 */
Harrison Mutaie0bc2c82025-05-08 15:36:08 +0000308struct entry_point_info *
309transfer_list_set_handoff_args(struct transfer_list_header *tl,
310 struct entry_point_info *ep_info);
311
Harrison Mutaib01ab962025-05-01 10:17:58 +0000312/**
313 * Get the data pointer of a transfer entry.
314 *
315 * Returns a pointer to the start of the entry's data buffer.
316 *
317 * @param[in] entry Pointer to the transfer entry.
318 *
319 * @return Pointer to the data section, or NULL on error.
320 */
321void *transfer_list_entry_data(struct transfer_list_entry *entry);
322
323/**
324 * Ensure the transfer list is initialized.
325 *
326 * Verifies that the transfer list has not already been initialized, then
327 * initializes it at the specified memory location.
328 *
329 * @param[in] addr Pointer to the memory to verify or initialize.
330 * @param[in] size Size of the memory in bytes.
331 *
332 * @return Pointer to a valid transfer list, or NULL on error.
333 */
334struct transfer_list_header *transfer_list_ensure(void *addr, size_t size);
335
336/**
337 * Dump the contents of a transfer list.
338 *
339 * @param[in] tl Pointer to the transfer list.
340 */
341void transfer_list_dump(struct transfer_list_header *tl);
342
343/**
344 * Dump the contents of a transfer entry.
345 *
346 * @param[in] te Pointer to the transfer entry.
347 */
348void transfer_entry_dump(struct transfer_list_entry *te);
349
Manish Pandey65fe3642025-03-21 12:44:42 +0000350#endif /* __ASSEMBLER__ */
351#endif /* TRANSFER_LIST_H */