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