• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SHIFT_64	UL(32)
33 #define REGISTER_CONVENTION_VERSION_SHIFT_32	UL(24)
34 #define REGISTER_CONVENTION_VERSION_MASK	UL(0xff)
35 #define REGISTER_CONVENTION_VERSION 	UL(1)
36 
37 #define TRANSFER_LIST_HANDOFF_X1_VALUE(__version) 	\
38 	((TRANSFER_LIST_SIGNATURE &	\
39 	((1UL << REGISTER_CONVENTION_VERSION_SHIFT_64) - 1)) | 	\
40 	(((__version) & REGISTER_CONVENTION_VERSION_MASK) <<	\
41 	 REGISTER_CONVENTION_VERSION_SHIFT_64))
42 
43 #define TRANSFER_LIST_HANDOFF_R1_VALUE(__version) 	\
44 	((TRANSFER_LIST_SIGNATURE &	\
45 	((1UL << REGISTER_CONVENTION_VERSION_SHIFT_32) - 1)) | 	\
46 	(((__version) & REGISTER_CONVENTION_VERSION_MASK) <<	\
47 	 REGISTER_CONVENTION_VERSION_SHIFT_32))
48 
49 #ifndef __ASSEMBLER__
50 
51 #define TL_FLAGS_HAS_CHECKSUM BIT(0)
52 
53 enum transfer_list_tag_id {
54 	TL_TAG_EMPTY = 0,
55 	TL_TAG_FDT = 1,
56 	TL_TAG_HOB_BLOCK = 2,
57 	TL_TAG_HOB_LIST = 3,
58 	TL_TAG_ACPI_TABLE_AGGREGATE = 4,
59 	TL_TAG_OPTEE_PAGABLE_PART = 0x100,
60 	TL_TAG_DT_SPMC_MANIFEST = 0x101,
61 	TL_TAG_EXEC_EP_INFO64 = 0x102,
62 	TL_TAG_TB_FW_CONFIG = 0x103,
63 	TL_TAG_SRAM_LAYOUT64 = 0x104,
64 };
65 
66 enum transfer_list_ops {
67 	TL_OPS_NON, /* invalid for any operation */
68 	TL_OPS_ALL, /* valid for all operations */
69 	TL_OPS_RO, /* valid for read only */
70 	TL_OPS_CUS, /* abort or switch to special code to interpret */
71 };
72 
73 struct transfer_list_header {
74 	uint32_t signature;
75 	uint8_t checksum;
76 	uint8_t version;
77 	uint8_t hdr_size;
78 	uint8_t alignment; /* max alignment of TE data */
79 	uint32_t size; /* TL header + all TEs */
80 	uint32_t max_size;
81 	uint32_t flags;
82 	uint32_t reserved; /* spare bytes */
83 	/*
84 	 * Commented out element used to visualize dynamic part of the
85 	 * data structure.
86 	 *
87 	 * Note that struct transfer_list_entry also is dynamic in size
88 	 * so the elements can't be indexed directly but instead must be
89 	 * traversed in order
90 	 *
91 	 * struct transfer_list_entry entries[];
92 	 */
93 };
94 
95 struct __attribute__((packed)) transfer_list_entry {
96 	uint32_t tag_id : 24;
97 	uint8_t hdr_size;
98 	uint32_t data_size;
99 	/*
100 	 * Commented out element used to visualize dynamic part of the
101 	 * data structure.
102 	 *
103 	 * Note that padding is added at the end of @data to make to reach
104 	 * a 8-byte boundary.
105 	 *
106 	 * uint8_t	data[ROUNDUP(data_size, 8)];
107 	 */
108 };
109 
110 CASSERT(sizeof(struct transfer_list_entry) == U(0x8), assert_transfer_list_entry_size);
111 
112 void transfer_list_dump(struct transfer_list_header *tl);
113 entry_point_info_t *
114 transfer_list_set_handoff_args(struct transfer_list_header *tl,
115 			       entry_point_info_t *ep_info);
116 struct transfer_list_header *transfer_list_init(void *addr, size_t max_size);
117 
118 struct transfer_list_header *
119 transfer_list_relocate(struct transfer_list_header *tl, void *addr,
120 		       size_t max_size);
121 enum transfer_list_ops
122 transfer_list_check_header(const struct transfer_list_header *tl);
123 
124 void transfer_list_update_checksum(struct transfer_list_header *tl);
125 bool transfer_list_verify_checksum(const struct transfer_list_header *tl);
126 
127 bool transfer_list_set_data_size(struct transfer_list_header *tl,
128 				 struct transfer_list_entry *entry,
129 				 uint32_t new_data_size);
130 
131 void *transfer_list_entry_data(struct transfer_list_entry *entry);
132 bool transfer_list_rem(struct transfer_list_header *tl,
133 		       struct transfer_list_entry *entry);
134 
135 struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl,
136 					      uint32_t tag_id,
137 					      uint32_t data_size,
138 					      const void *data);
139 
140 struct transfer_list_entry *
141 transfer_list_add_with_align(struct transfer_list_header *tl, uint32_t tag_id,
142 			     uint32_t data_size, const void *data,
143 			     uint8_t alignment);
144 
145 struct transfer_list_entry *
146 transfer_list_next(struct transfer_list_header *tl,
147 		   struct transfer_list_entry *last);
148 
149 struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
150 					       uint32_t tag_id);
151 
152 #endif /*__ASSEMBLER__*/
153 #endif /*__TRANSFER_LIST_H*/
154