1*42ebaae3SMarek Vasut /* 2*42ebaae3SMarek Vasut * include/linker_lists.h 3*42ebaae3SMarek Vasut * 4*42ebaae3SMarek Vasut * Implementation of linker-generated arrays 5*42ebaae3SMarek Vasut * 6*42ebaae3SMarek Vasut * Copyright (C) 2012 Marek Vasut <marex@denx.de> 7*42ebaae3SMarek Vasut * 8*42ebaae3SMarek Vasut * See file CREDITS for list of people who contributed to this 9*42ebaae3SMarek Vasut * project. 10*42ebaae3SMarek Vasut * 11*42ebaae3SMarek Vasut * This program is free software; you can redistribute it and/or 12*42ebaae3SMarek Vasut * modify it under the terms of the GNU General Public License as 13*42ebaae3SMarek Vasut * published by the Free Software Foundation; either version 2 of 14*42ebaae3SMarek Vasut * the License, or (at your option) any later version. 15*42ebaae3SMarek Vasut */ 16*42ebaae3SMarek Vasut #ifndef __LINKER_LISTS_H__ 17*42ebaae3SMarek Vasut #define __LINKER_LISTS_H__ 18*42ebaae3SMarek Vasut 19*42ebaae3SMarek Vasut /** 20*42ebaae3SMarek Vasut * ll_entry_declare() - Declare linker-generated array entry 21*42ebaae3SMarek Vasut * @_type: Data type of the entry 22*42ebaae3SMarek Vasut * @_name: Name of the entry 23*42ebaae3SMarek Vasut * @_section_u: Subsection of u_boot_list in which this entry is placed 24*42ebaae3SMarek Vasut * (with underscores instead of dots, for name concatenation) 25*42ebaae3SMarek Vasut * @_section_d: Subsection of u_boot_list in which this entry is placed 26*42ebaae3SMarek Vasut * (with dots, for section concatenation) 27*42ebaae3SMarek Vasut * 28*42ebaae3SMarek Vasut * This macro declares a variable that is placed into a linker-generated 29*42ebaae3SMarek Vasut * array. This is a basic building block for more advanced use of linker- 30*42ebaae3SMarek Vasut * generated arrays. The user is expected to build their own macro wrapper 31*42ebaae3SMarek Vasut * around this one. 32*42ebaae3SMarek Vasut * 33*42ebaae3SMarek Vasut * A variable declared using this macro must be compile-time initialized 34*42ebaae3SMarek Vasut * and is as such placed into subsection of special section, .u_boot_list. 35*42ebaae3SMarek Vasut * The subsection is specified by the _section_[u,d] parameter, see below. 36*42ebaae3SMarek Vasut * The base name of the variable is _name, yet the actual variable is 37*42ebaae3SMarek Vasut * declared as concatenation of 38*42ebaae3SMarek Vasut * 39*42ebaae3SMarek Vasut * %_u_boot_list_ + @_section_u + _ + @_name 40*42ebaae3SMarek Vasut * 41*42ebaae3SMarek Vasut * which ensures name uniqueness. This variable shall never be refered 42*42ebaae3SMarek Vasut * directly though. 43*42ebaae3SMarek Vasut * 44*42ebaae3SMarek Vasut * Special precaution must be made when using this macro: 45*42ebaae3SMarek Vasut * 1) The _type must not contain the "static" keyword, otherwise the entry 46*42ebaae3SMarek Vasut * is not generated. 47*42ebaae3SMarek Vasut * 48*42ebaae3SMarek Vasut * 2) The @_section_u and @_section_d variables must match, the only difference 49*42ebaae3SMarek Vasut * is that in @_section_u is every dot "." character present in @_section_d 50*42ebaae3SMarek Vasut * replaced by a single underscore "_" character in @_section_u. The actual 51*42ebaae3SMarek Vasut * purpose of these parameters is to select proper subsection in the global 52*42ebaae3SMarek Vasut * .u_boot_list section. 53*42ebaae3SMarek Vasut * 54*42ebaae3SMarek Vasut * 3) In case a section is declared that contains some array elements AND a 55*42ebaae3SMarek Vasut * subsection of this section is declared and contains some elements, it is 56*42ebaae3SMarek Vasut * imperative that the elements are of the same type. 57*42ebaae3SMarek Vasut * 58*42ebaae3SMarek Vasut * 4) In case an outer section is declared that contains some array elements 59*42ebaae3SMarek Vasut * AND am inner subsection of this section is declared and contains some 60*42ebaae3SMarek Vasut * elements, then when traversing the outer section, even the elements of 61*42ebaae3SMarek Vasut * the inner sections are present in the array. 62*42ebaae3SMarek Vasut * 63*42ebaae3SMarek Vasut * Example: 64*42ebaae3SMarek Vasut * ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub, cmd.sub) = { 65*42ebaae3SMarek Vasut * .x = 3, 66*42ebaae3SMarek Vasut * .y = 4, 67*42ebaae3SMarek Vasut * }; 68*42ebaae3SMarek Vasut */ 69*42ebaae3SMarek Vasut #define ll_entry_declare(_type, _name, _section_u, _section_d) \ 70*42ebaae3SMarek Vasut _type _u_boot_list_##_section_u##_##_name __attribute__(( \ 71*42ebaae3SMarek Vasut unused, aligned(4), \ 72*42ebaae3SMarek Vasut section(".u_boot_list."#_section_d"."#_name))) 73*42ebaae3SMarek Vasut 74*42ebaae3SMarek Vasut /** 75*42ebaae3SMarek Vasut * ll_entry_start() - Point to first entry of linker-generated array 76*42ebaae3SMarek Vasut * @_type: Data type of the entry 77*42ebaae3SMarek Vasut * @_section_u: Subsection of u_boot_list in which this entry is placed 78*42ebaae3SMarek Vasut * (with underscores instead of dots) 79*42ebaae3SMarek Vasut * 80*42ebaae3SMarek Vasut * This function returns (_type *) pointer to the very first entry of a 81*42ebaae3SMarek Vasut * linker-generated array placed into subsection of .u_boot_list section 82*42ebaae3SMarek Vasut * specified by _section_u argument. 83*42ebaae3SMarek Vasut * 84*42ebaae3SMarek Vasut * Example: 85*42ebaae3SMarek Vasut * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub); 86*42ebaae3SMarek Vasut */ 87*42ebaae3SMarek Vasut #define ll_entry_start(_type, _section_u) \ 88*42ebaae3SMarek Vasut ({ \ 89*42ebaae3SMarek Vasut extern _type _u_boot_list_##_section_u##__start; \ 90*42ebaae3SMarek Vasut _type *_ll_result = &_u_boot_list_##_section_u##__start;\ 91*42ebaae3SMarek Vasut _ll_result; \ 92*42ebaae3SMarek Vasut }) 93*42ebaae3SMarek Vasut 94*42ebaae3SMarek Vasut /** 95*42ebaae3SMarek Vasut * ll_entry_count() - Return the number of elements in linker-generated array 96*42ebaae3SMarek Vasut * @_type: Data type of the entry 97*42ebaae3SMarek Vasut * @_section_u: Subsection of u_boot_list in which this entry is placed 98*42ebaae3SMarek Vasut * (with underscores instead of dots) 99*42ebaae3SMarek Vasut * 100*42ebaae3SMarek Vasut * This function returns the number of elements of a linker-generated array 101*42ebaae3SMarek Vasut * placed into subsection of .u_boot_list section specified by _section_u 102*42ebaae3SMarek Vasut * argument. The result is of an unsigned int type. 103*42ebaae3SMarek Vasut * 104*42ebaae3SMarek Vasut * Example: 105*42ebaae3SMarek Vasut * int i; 106*42ebaae3SMarek Vasut * const unsigned int count = ll_entry_count(struct my_sub_cmd, cmd_sub); 107*42ebaae3SMarek Vasut * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub); 108*42ebaae3SMarek Vasut * for (i = 0; i < count; i++, msc++) 109*42ebaae3SMarek Vasut * printf("Entry %i, x=%i y=%i\n", i, msc->x, msc->y); 110*42ebaae3SMarek Vasut */ 111*42ebaae3SMarek Vasut #define ll_entry_count(_type, _section_u) \ 112*42ebaae3SMarek Vasut ({ \ 113*42ebaae3SMarek Vasut extern _type _u_boot_list_##_section_u##__start; \ 114*42ebaae3SMarek Vasut extern _type _u_boot_list_##_section_u##__end; \ 115*42ebaae3SMarek Vasut unsigned int _ll_result = \ 116*42ebaae3SMarek Vasut &_u_boot_list_##_section_u##__end - \ 117*42ebaae3SMarek Vasut &_u_boot_list_##_section_u##__start; \ 118*42ebaae3SMarek Vasut _ll_result; \ 119*42ebaae3SMarek Vasut }) 120*42ebaae3SMarek Vasut 121*42ebaae3SMarek Vasut 122*42ebaae3SMarek Vasut /** 123*42ebaae3SMarek Vasut * ll_entry_get() - Retrieve entry from linker-generated array by name 124*42ebaae3SMarek Vasut * @_type: Data type of the entry 125*42ebaae3SMarek Vasut * @_name: Name of the entry 126*42ebaae3SMarek Vasut * @_section_u: Subsection of u_boot_list in which this entry is placed 127*42ebaae3SMarek Vasut * (with underscores instead of dots) 128*42ebaae3SMarek Vasut * 129*42ebaae3SMarek Vasut * This function returns a pointer to a particular entry in LG-array 130*42ebaae3SMarek Vasut * identified by the subsection of u_boot_list where the entry resides 131*42ebaae3SMarek Vasut * and it's name. 132*42ebaae3SMarek Vasut * 133*42ebaae3SMarek Vasut * Example: 134*42ebaae3SMarek Vasut * ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub, cmd.sub) = { 135*42ebaae3SMarek Vasut * .x = 3, 136*42ebaae3SMarek Vasut * .y = 4, 137*42ebaae3SMarek Vasut * }; 138*42ebaae3SMarek Vasut * ... 139*42ebaae3SMarek Vasut * struct my_sub_cmd *c = ll_entry_get(struct my_sub_cmd, my_sub_cmd, cmd_sub); 140*42ebaae3SMarek Vasut */ 141*42ebaae3SMarek Vasut #define ll_entry_get(_type, _name, _section_u) \ 142*42ebaae3SMarek Vasut ({ \ 143*42ebaae3SMarek Vasut extern _type _u_boot_list_##_section_u##_##_name; \ 144*42ebaae3SMarek Vasut _type *_ll_result = &_u_boot_list_##_section_u##_##_name;\ 145*42ebaae3SMarek Vasut _ll_result; \ 146*42ebaae3SMarek Vasut }) 147*42ebaae3SMarek Vasut 148*42ebaae3SMarek Vasut #endif /* __LINKER_LISTS_H__ */ 149