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