1 /*
2  * Copyright (c) 2023-2024, Linaro Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef __TRANSFER_LIST_H
8 #define __TRANSFER_LIST_H
9 
10 #include <stdbool.h>
11 #include <stdint.h>
12 
13 #include <common/ep_info.h>
14 #include <lib/utils_def.h>
15 
16 #define TRANSFER_LIST_SIGNATURE U(0x4a0fb10b)
17 #define TRANSFER_LIST_VERSION U(0x0001)
18 
19 /*
20  * Init value of maximum alignment required by any TE data in the TL
21  * specified as a power of two
22  */
23 #define TRANSFER_LIST_INIT_MAX_ALIGN U(3)
24 
25 /* Alignment required by TE header start address, in bytes */
26 #define TRANSFER_LIST_GRANULE U(8)
27 
28 /*
29  * Version of the register convention used.
30  * Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9
31  */
32 #define REGISTER_CONVENTION_VERSION_MASK (1 << 24)
33 
34 #ifndef __ASSEMBLER__
35 
36 #define TL_FLAGS_HAS_CHECKSUM BIT(0)
37 
38 enum transfer_list_tag_id {
39 	TL_TAG_EMPTY = 0,
40 	TL_TAG_FDT = 1,
41 	TL_TAG_HOB_BLOCK = 2,
42 	TL_TAG_HOB_LIST = 3,
43 	TL_TAG_ACPI_TABLE_AGGREGATE = 4,
44 	TL_TAG_OPTEE_PAGABLE_PART = 0x100,
45 	TL_TAG_DT_SPMC_MANIFEST = 0x101,
46 	TL_TAG_EXEC_EP_INFO64 = 0x102,
47 	TL_TAG_TB_FW_CONFIG = 0x103,
48 	TL_TAG_SRAM_LAYOUT64 = 0x104,
49 };
50 
51 enum transfer_list_ops {
52 	TL_OPS_NON, /* invalid for any operation */
53 	TL_OPS_ALL, /* valid for all operations */
54 	TL_OPS_RO, /* valid for read only */
55 	TL_OPS_CUS, /* abort or switch to special code to interpret */
56 };
57 
58 struct transfer_list_header {
59 	uint32_t signature;
60 	uint8_t checksum;
61 	uint8_t version;
62 	uint8_t hdr_size;
63 	uint8_t alignment; /* max alignment of TE data */
64 	uint32_t size; /* TL header + all TEs */
65 	uint32_t max_size;
66 	uint32_t flags;
67 	uint32_t reserved; /* spare bytes */
68 	/*
69 	 * Commented out element used to visualize dynamic part of the
70 	 * data structure.
71 	 *
72 	 * Note that struct transfer_list_entry also is dynamic in size
73 	 * so the elements can't be indexed directly but instead must be
74 	 * traversed in order
75 	 *
76 	 * struct transfer_list_entry entries[];
77 	 */
78 };
79 
80 struct __attribute__((packed)) transfer_list_entry {
81 	uint32_t tag_id : 24;
82 	uint8_t hdr_size;
83 	uint32_t data_size;
84 	/*
85 	 * Commented out element used to visualize dynamic part of the
86 	 * data structure.
87 	 *
88 	 * Note that padding is added at the end of @data to make to reach
89 	 * a 8-byte boundary.
90 	 *
91 	 * uint8_t	data[ROUNDUP(data_size, 8)];
92 	 */
93 };
94 
95 CASSERT(sizeof(struct transfer_list_entry) == U(0x8), assert_transfer_list_entry_size);
96 
97 void transfer_list_dump(struct transfer_list_header *tl);
98 entry_point_info_t *
99 transfer_list_set_handoff_args(struct transfer_list_header *tl,
100 			       entry_point_info_t *ep_info);
101 struct transfer_list_header *transfer_list_init(void *addr, size_t max_size);
102 
103 struct transfer_list_header *
104 transfer_list_relocate(struct transfer_list_header *tl, void *addr,
105 		       size_t max_size);
106 enum transfer_list_ops
107 transfer_list_check_header(const struct transfer_list_header *tl);
108 
109 void transfer_list_update_checksum(struct transfer_list_header *tl);
110 bool transfer_list_verify_checksum(const struct transfer_list_header *tl);
111 
112 bool transfer_list_set_data_size(struct transfer_list_header *tl,
113 				 struct transfer_list_entry *entry,
114 				 uint32_t new_data_size);
115 
116 void *transfer_list_entry_data(struct transfer_list_entry *entry);
117 bool transfer_list_rem(struct transfer_list_header *tl,
118 		       struct transfer_list_entry *entry);
119 
120 struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl,
121 					      uint32_t tag_id,
122 					      uint32_t data_size,
123 					      const void *data);
124 
125 struct transfer_list_entry *
126 transfer_list_add_with_align(struct transfer_list_header *tl, uint32_t tag_id,
127 			     uint32_t data_size, const void *data,
128 			     uint8_t alignment);
129 
130 struct transfer_list_entry *
131 transfer_list_next(struct transfer_list_header *tl,
132 		   struct transfer_list_entry *last);
133 
134 struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
135 					       uint32_t tag_id);
136 
137 #endif /*__ASSEMBLER__*/
138 #endif /*__TRANSFER_LIST_H*/
139