xref: /optee_os/core/include/scattered_array.h (revision 5e4210e9ea0328a62dc4a5919a28ce3092ee7287)
1*5e4210e9SJens Wiklander /* SPDX-License-Identifier: BSD-2-Clause */
2*5e4210e9SJens Wiklander /*
3*5e4210e9SJens Wiklander  * Copyright (c) 2018, Linaro Limited
4*5e4210e9SJens Wiklander  */
5*5e4210e9SJens Wiklander #ifndef __SCATTERED_ARRAY_H
6*5e4210e9SJens Wiklander #define __SCATTERED_ARRAY_H
7*5e4210e9SJens Wiklander 
8*5e4210e9SJens Wiklander #include <compiler.h>
9*5e4210e9SJens Wiklander #include <keep.h>
10*5e4210e9SJens Wiklander 
11*5e4210e9SJens Wiklander /*
12*5e4210e9SJens Wiklander  * A scattered array is assembled from items declared in different source
13*5e4210e9SJens Wiklander  * files depending on something like "SORT(.scattered_array*)" in the link
14*5e4210e9SJens Wiklander  * script to get everything assembled in the right order.
15*5e4210e9SJens Wiklander  *
16*5e4210e9SJens Wiklander  * Whenever a new scattered array is created with the macros below there's
17*5e4210e9SJens Wiklander  * no need to update the link script.
18*5e4210e9SJens Wiklander  */
19*5e4210e9SJens Wiklander 
20*5e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_ITEM3(element_type, element_name, section_name) \
21*5e4210e9SJens Wiklander 	static const element_type element_name; \
22*5e4210e9SJens Wiklander 	KEEP_INIT(element_name); \
23*5e4210e9SJens Wiklander 	static const element_type element_name __used \
24*5e4210e9SJens Wiklander 		__section(section_name __SECTION_FLAGS_RODATA)
25*5e4210e9SJens Wiklander 
26*5e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_PG_ITEM3(element_type, element_name, section_name) \
27*5e4210e9SJens Wiklander 	static const element_type element_name __used \
28*5e4210e9SJens Wiklander 		__section(section_name __SECTION_FLAGS_RODATA)
29*5e4210e9SJens Wiklander 
30*5e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type) \
31*5e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_ITEM3(element_type, \
32*5e4210e9SJens Wiklander 			      __scattered_array_ ## id ## array_name, \
33*5e4210e9SJens Wiklander 			      ".scattered_array_" #array_name "_1_" #order)
34*5e4210e9SJens Wiklander 
35*5e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type) \
36*5e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_PG_ITEM3(element_type, \
37*5e4210e9SJens Wiklander 				 __scattered_array_ ## id ## array_name, \
38*5e4210e9SJens Wiklander 				 ".scattered_array_" #array_name "_1_" #order)
39*5e4210e9SJens Wiklander 
40*5e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_ITEM1(array_name, order, id, element_type) \
41*5e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type)
42*5e4210e9SJens Wiklander 
43*5e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_PG_ITEM1(array_name, order, id, element_type) \
44*5e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type)
45*5e4210e9SJens Wiklander 
46*5e4210e9SJens Wiklander /*
47*5e4210e9SJens Wiklander  * Defines an item in a scattered array, sorted based on @order.
48*5e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
49*5e4210e9SJens Wiklander  * @order:        Tag on which this item is sorted in the array
50*5e4210e9SJens Wiklander  * @element_type: The type of the elemenet
51*5e4210e9SJens Wiklander  */
52*5e4210e9SJens Wiklander #define SCATTERED_ARRAY_DEFINE_ITEM_ORDERED(array_name, order, element_type) \
53*5e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_ITEM1(array_name, order, __COUNTER__, element_type)
54*5e4210e9SJens Wiklander 
55*5e4210e9SJens Wiklander /*
56*5e4210e9SJens Wiklander  * Same as SCATTERED_ARRAY_DEFINE_ITEM_ORDERED except that references
57*5e4210e9SJens Wiklander  * to other objects (for instance null terminated strings) are allowed
58*5e4210e9SJens Wiklander  * to reside in the paged area without residing in the init area
59*5e4210e9SJens Wiklander  */
60*5e4210e9SJens Wiklander #define SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(array_name, order, \
61*5e4210e9SJens Wiklander 					       element_type) \
62*5e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_PG_ITEM1(array_name, order, __COUNTER__, element_type)
63*5e4210e9SJens Wiklander 
64*5e4210e9SJens Wiklander /*
65*5e4210e9SJens Wiklander  * Defines an item in a scattered array
66*5e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
67*5e4210e9SJens Wiklander  * @element_type: The type of the elemenet
68*5e4210e9SJens Wiklander  */
69*5e4210e9SJens Wiklander #define SCATTERED_ARRAY_DEFINE_ITEM(array_name, element_type) \
70*5e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_ITEM1(array_name, 0, __COUNTER__, element_type)
71*5e4210e9SJens Wiklander 
72*5e4210e9SJens Wiklander /*
73*5e4210e9SJens Wiklander  * Same as SCATTERED_ARRAY_DEFINE_ITEM except that references to other
74*5e4210e9SJens Wiklander  * objects (for instance null terminated strings) are allowed to reside in
75*5e4210e9SJens Wiklander  * the paged area without residing in the init area
76*5e4210e9SJens Wiklander  */
77*5e4210e9SJens Wiklander #define SCATTERED_ARRAY_DEFINE_PG_ITEM(array_name, element_type) \
78*5e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_PG_ITEM1(array_name, 0, __COUNTER__, element_type)
79*5e4210e9SJens Wiklander 
80*5e4210e9SJens Wiklander /*
81*5e4210e9SJens Wiklander  * Returns the first element in a scattered array
82*5e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
83*5e4210e9SJens Wiklander  * @element_type: The type of the elemenet
84*5e4210e9SJens Wiklander  */
85*5e4210e9SJens Wiklander #define SCATTERED_ARRAY_BEGIN(array_name, element_type) (__extension__({ \
86*5e4210e9SJens Wiklander 		static const element_type __scattered_array_begin[0] __unused \
87*5e4210e9SJens Wiklander 		__section(".scattered_array_" #array_name "_0" \
88*5e4210e9SJens Wiklander 			  __SECTION_FLAGS_RODATA); \
89*5e4210e9SJens Wiklander 		\
90*5e4210e9SJens Wiklander 		(const element_type *)scattered_array_relax_ptr( \
91*5e4210e9SJens Wiklander 			__scattered_array_begin); \
92*5e4210e9SJens Wiklander 	}))
93*5e4210e9SJens Wiklander 
94*5e4210e9SJens Wiklander /*
95*5e4210e9SJens Wiklander  * Returns one entry past the last element in a scattered array
96*5e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
97*5e4210e9SJens Wiklander  * @element_type: The type of the elemenet
98*5e4210e9SJens Wiklander  */
99*5e4210e9SJens Wiklander #define SCATTERED_ARRAY_END(array_name, element_type) (__extension__({ \
100*5e4210e9SJens Wiklander 		static const element_type __scattered_array_end[0] __unused \
101*5e4210e9SJens Wiklander 		__section(".scattered_array_" #array_name "_2" \
102*5e4210e9SJens Wiklander 			  __SECTION_FLAGS_RODATA); \
103*5e4210e9SJens Wiklander 		\
104*5e4210e9SJens Wiklander 		__scattered_array_end; \
105*5e4210e9SJens Wiklander 	}))
106*5e4210e9SJens Wiklander 
107*5e4210e9SJens Wiklander /*
108*5e4210e9SJens Wiklander  * Loop over all elements in the scattered array
109*5e4210e9SJens Wiklander  * @elem:	Iterator
110*5e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
111*5e4210e9SJens Wiklander  * @element_type: The type of the elemenet
112*5e4210e9SJens Wiklander  */
113*5e4210e9SJens Wiklander #define SCATTERED_ARRAY_FOREACH(elem, array_name, element_type) \
114*5e4210e9SJens Wiklander 	for ((elem) = SCATTERED_ARRAY_BEGIN(array_name, element_type); \
115*5e4210e9SJens Wiklander 	     (elem) < SCATTERED_ARRAY_END(array_name, element_type); (elem)++)
116*5e4210e9SJens Wiklander 
117*5e4210e9SJens Wiklander /*
118*5e4210e9SJens Wiklander  * scattered_array_relax_ptr() - relax pointer attributes
119*5e4210e9SJens Wiklander  * @p	pointer to return
120*5e4210e9SJens Wiklander  *
121*5e4210e9SJens Wiklander  * If the pointer returned from the array __scattered_array_begin[] in
122*5e4210e9SJens Wiklander  * SCATTERED_ARRAY_BEGIN() is passed directly the compiler may notice that
123*5e4210e9SJens Wiklander  * it's an empty array and emit warnings. With the address passed via this
124*5e4210e9SJens Wiklander  * function the compiler will have no such knowledge about the pointer.
125*5e4210e9SJens Wiklander  *
126*5e4210e9SJens Wiklander  * Returns supplied pointer.
127*5e4210e9SJens Wiklander  */
128*5e4210e9SJens Wiklander const void *scattered_array_relax_ptr(const void *p) __attr_const;
129*5e4210e9SJens Wiklander 
130*5e4210e9SJens Wiklander #endif /*__SCATTERED_ARRAY_H*/
131*5e4210e9SJens Wiklander 
132