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