xref: /optee_os/core/include/scattered_array.h (revision c0af48e60848a9873f145d65ccdc0ad36bc43afb)
15e4210e9SJens Wiklander /* SPDX-License-Identifier: BSD-2-Clause */
25e4210e9SJens Wiklander /*
35e4210e9SJens Wiklander  * Copyright (c) 2018, Linaro Limited
45e4210e9SJens Wiklander  */
55e4210e9SJens Wiklander #ifndef __SCATTERED_ARRAY_H
65e4210e9SJens Wiklander #define __SCATTERED_ARRAY_H
75e4210e9SJens Wiklander 
85e4210e9SJens Wiklander #include <compiler.h>
95e4210e9SJens Wiklander #include <keep.h>
105e4210e9SJens Wiklander 
115e4210e9SJens Wiklander /*
125e4210e9SJens Wiklander  * A scattered array is assembled from items declared in different source
135e4210e9SJens Wiklander  * files depending on something like "SORT(.scattered_array*)" in the link
145e4210e9SJens Wiklander  * script to get everything assembled in the right order.
155e4210e9SJens Wiklander  *
165e4210e9SJens Wiklander  * Whenever a new scattered array is created with the macros below there's
175e4210e9SJens Wiklander  * no need to update the link script.
185e4210e9SJens Wiklander  */
195e4210e9SJens Wiklander 
205e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_ITEM3(element_type, element_name, section_name) \
215e4210e9SJens Wiklander 	static const element_type element_name; \
223639b55fSJerome Forissier 	DECLARE_KEEP_INIT(element_name); \
235e4210e9SJens Wiklander 	static const element_type element_name __used \
24*c0af48e6SJerome Forissier 		__section(section_name)
255e4210e9SJens Wiklander 
265e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_PG_ITEM3(element_type, element_name, section_name) \
275e4210e9SJens Wiklander 	static const element_type element_name __used \
28*c0af48e6SJerome Forissier 		__section(section_name)
295e4210e9SJens Wiklander 
305e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type) \
315e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_ITEM3(element_type, \
325e4210e9SJens Wiklander 			      __scattered_array_ ## id ## array_name, \
335e4210e9SJens Wiklander 			      ".scattered_array_" #array_name "_1_" #order)
345e4210e9SJens Wiklander 
355e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type) \
365e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_PG_ITEM3(element_type, \
375e4210e9SJens Wiklander 				 __scattered_array_ ## id ## array_name, \
385e4210e9SJens Wiklander 				 ".scattered_array_" #array_name "_1_" #order)
395e4210e9SJens Wiklander 
405e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_ITEM1(array_name, order, id, element_type) \
415e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type)
425e4210e9SJens Wiklander 
435e4210e9SJens Wiklander #define __SCT_ARRAY_DEF_PG_ITEM1(array_name, order, id, element_type) \
445e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type)
455e4210e9SJens Wiklander 
465e4210e9SJens Wiklander /*
475e4210e9SJens Wiklander  * Defines an item in a scattered array, sorted based on @order.
485e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
495e4210e9SJens Wiklander  * @order:        Tag on which this item is sorted in the array
505e4210e9SJens Wiklander  * @element_type: The type of the elemenet
515e4210e9SJens Wiklander  */
525e4210e9SJens Wiklander #define SCATTERED_ARRAY_DEFINE_ITEM_ORDERED(array_name, order, element_type) \
535e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_ITEM1(array_name, order, __COUNTER__, element_type)
545e4210e9SJens Wiklander 
555e4210e9SJens Wiklander /*
565e4210e9SJens Wiklander  * Same as SCATTERED_ARRAY_DEFINE_ITEM_ORDERED except that references
575e4210e9SJens Wiklander  * to other objects (for instance null terminated strings) are allowed
585e4210e9SJens Wiklander  * to reside in the paged area without residing in the init area
595e4210e9SJens Wiklander  */
605e4210e9SJens Wiklander #define SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(array_name, order, \
615e4210e9SJens Wiklander 					       element_type) \
625e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_PG_ITEM1(array_name, order, __COUNTER__, element_type)
635e4210e9SJens Wiklander 
645e4210e9SJens Wiklander /*
655e4210e9SJens Wiklander  * Defines an item in a scattered array
665e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
675e4210e9SJens Wiklander  * @element_type: The type of the elemenet
685e4210e9SJens Wiklander  */
695e4210e9SJens Wiklander #define SCATTERED_ARRAY_DEFINE_ITEM(array_name, element_type) \
705e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_ITEM1(array_name, 0, __COUNTER__, element_type)
715e4210e9SJens Wiklander 
725e4210e9SJens Wiklander /*
735e4210e9SJens Wiklander  * Same as SCATTERED_ARRAY_DEFINE_ITEM except that references to other
745e4210e9SJens Wiklander  * objects (for instance null terminated strings) are allowed to reside in
755e4210e9SJens Wiklander  * the paged area without residing in the init area
765e4210e9SJens Wiklander  */
775e4210e9SJens Wiklander #define SCATTERED_ARRAY_DEFINE_PG_ITEM(array_name, element_type) \
785e4210e9SJens Wiklander 	__SCT_ARRAY_DEF_PG_ITEM1(array_name, 0, __COUNTER__, element_type)
795e4210e9SJens Wiklander 
805e4210e9SJens Wiklander /*
815e4210e9SJens Wiklander  * Returns the first element in a scattered array
825e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
835e4210e9SJens Wiklander  * @element_type: The type of the elemenet
845e4210e9SJens Wiklander  */
855e4210e9SJens Wiklander #define SCATTERED_ARRAY_BEGIN(array_name, element_type) (__extension__({ \
865e4210e9SJens Wiklander 		static const element_type __scattered_array_begin[0] __unused \
87*c0af48e6SJerome Forissier 		__section(".scattered_array_" #array_name "_0"); \
885e4210e9SJens Wiklander 		\
895e4210e9SJens Wiklander 		(const element_type *)scattered_array_relax_ptr( \
905e4210e9SJens Wiklander 			__scattered_array_begin); \
915e4210e9SJens Wiklander 	}))
925e4210e9SJens Wiklander 
935e4210e9SJens Wiklander /*
945e4210e9SJens Wiklander  * Returns one entry past the last element in a scattered array
955e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
965e4210e9SJens Wiklander  * @element_type: The type of the elemenet
975e4210e9SJens Wiklander  */
985e4210e9SJens Wiklander #define SCATTERED_ARRAY_END(array_name, element_type) (__extension__({ \
995e4210e9SJens Wiklander 		static const element_type __scattered_array_end[0] __unused \
100*c0af48e6SJerome Forissier 		__section(".scattered_array_" #array_name "_2"); \
1015e4210e9SJens Wiklander 		\
1025e4210e9SJens Wiklander 		__scattered_array_end; \
1035e4210e9SJens Wiklander 	}))
1045e4210e9SJens Wiklander 
1055e4210e9SJens Wiklander /*
1065e4210e9SJens Wiklander  * Loop over all elements in the scattered array
1075e4210e9SJens Wiklander  * @elem:	Iterator
1085e4210e9SJens Wiklander  * @array_name:   Name of the scattered array
1095e4210e9SJens Wiklander  * @element_type: The type of the elemenet
1105e4210e9SJens Wiklander  */
1115e4210e9SJens Wiklander #define SCATTERED_ARRAY_FOREACH(elem, array_name, element_type) \
1125e4210e9SJens Wiklander 	for ((elem) = SCATTERED_ARRAY_BEGIN(array_name, element_type); \
1135e4210e9SJens Wiklander 	     (elem) < SCATTERED_ARRAY_END(array_name, element_type); (elem)++)
1145e4210e9SJens Wiklander 
1155e4210e9SJens Wiklander /*
1165e4210e9SJens Wiklander  * scattered_array_relax_ptr() - relax pointer attributes
1175e4210e9SJens Wiklander  * @p	pointer to return
1185e4210e9SJens Wiklander  *
1195e4210e9SJens Wiklander  * If the pointer returned from the array __scattered_array_begin[] in
1205e4210e9SJens Wiklander  * SCATTERED_ARRAY_BEGIN() is passed directly the compiler may notice that
1215e4210e9SJens Wiklander  * it's an empty array and emit warnings. With the address passed via this
1225e4210e9SJens Wiklander  * function the compiler will have no such knowledge about the pointer.
1235e4210e9SJens Wiklander  *
1245e4210e9SJens Wiklander  * Returns supplied pointer.
1255e4210e9SJens Wiklander  */
1265e4210e9SJens Wiklander const void *scattered_array_relax_ptr(const void *p) __attr_const;
1275e4210e9SJens Wiklander 
1285e4210e9SJens Wiklander #endif /*__SCATTERED_ARRAY_H*/
1295e4210e9SJens Wiklander 
130