linker_lists.h 5.4 KB

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