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