Hi Marek, On Sun, Sep 23, 2012 at 8:21 PM, Marek Vasut <ma...@denx.de> wrote: > This patch adds support for linker-generated array. These arrays > are a generalization of the U-Boot command declaration approach. > > Basically, the idea is to generate an array, where elements of the > array are statically initialized at compiler time and each element > is declared separatelly at different place. Such array though can > later be accessed and used via special accessor. > > The actual implementation relies on placing any variable that is to > represent an element of LG-array into subsection of .u_boot_list > linker section . Once compiled, it is possible to dump all symbols > placed in .u_boot_list section and generate appropriate bounds for > each subsection of the .u_boot_list section. Each such subsection > this contains .__start and .__end entries at the begining and end > respecitively. > > This allows for simple run-time traversing of the array, since the > symbols are properly defined. > > Signed-off-by: Marek Vasut <ma...@denx.de> > Cc: Joe Hershberger <joe.hershber...@gmail.com> > Cc: Mike Frysinger <vap...@gentoo.org> > --- > include/linker_lists.h | 125 > ++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 125 insertions(+) > create mode 100644 include/linker_lists.h > > diff --git a/include/linker_lists.h b/include/linker_lists.h > new file mode 100644 > index 0000000..ffa95f6 > --- /dev/null > +++ b/include/linker_lists.h > @@ -0,0 +1,125 @@ > +/* > + * include/linker_lists.h > + * > + * Implementation of linker-generated arrays > + * > + * Copyright (C) 2012 Marek Vasut <ma...@denx.de> > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ > +#ifndef __LINKER_LISTS_H__ > +#define __LINKER_LISTS_H__ > + > +/** > + * ll_entry_declare() - Declare linker-generated array entry > + * _type: Data type of the entry > + * _name: Name of the entry > + * _section_u: Subsection of u_boot_list in which this entry is placed > + * (with underscores instead of dots, for name concatenation) > + * _section_d: Subsection of u_boot_list in which this entry is placed > + * (with dots, for section concatenation) > + * > + * This macro declares a variable that is placed into a linker-generated > + * array. This is a basic building block for more advanced use of linker- > + * generated arrays. The user is expected to build their own macro wrapper > + * around this one. > + * > + * A variable declared using this macro must be compile-time initialized > + * and is as such placed into subsection of special section, .u_boot_list. > + * The subsection is specified by the _section_[u,d] parameter, see below. > + * The base name of the variable is _name, yet the actual variable is > + * declared as concatenation of: > + * > + * _u_boot_list_ + _section_u + _ + _name > + * > + * which ensures name uniqueness. This variable shall never be refered > + * directly though. > + * > + * Special precaution must be made when using this macro: > + * > + * 1) The _type must not contain the "static" keyword, otherwise the entry > + * is not generated. > + * 2) The _section_u and _section_d variables must match, the only difference > + * is that in _section_u is every dot "." character present in _section_d > + * replaced by a single underscore "_" character in _section_u. The actual > + * purpose of these parameters is to select proper subsection in the > global > + * .u_boot_list section. > + * 3) In case a section is declared that contains some array elements AND a > + * subsection of this section is declared and contains some elements, it > is > + * imperative that the elements are of the same type. > + * 4) In case an outer section is declared that contains some array elements > + * AND am inner subsection of this section is declared and contains some > + * elements, then when traversing the outer section, even the elements of > + * the inner sections are present in the array. > + * > + * Example of usage: > + * > + * ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub, cmd.sub) = { > + * .x = 3, > + * .y = 4, > + * }; > + */ > +#define ll_entry_declare(_type, _name, _section_u, _section_d) \ > + _type _u_boot_list_##_section_u##_##_name __attribute__(( \ > + unused, aligned(4), \ > + section(".u_boot_list."#_section_d"."#_name))); \ > + _type _u_boot_list_##_section_u##_##_name
Why repeat the "_type _u_boot_list_##_section_u##_##_name" instead of just leaving the semicolon off after the __attribute__()? > + > +/** > + * ll_entry_start() - Point to first entry of linker-generated array > + * _type: Data type of the entry > + * _section_u: Subsection of u_boot_list in which this entry is placed > + * (with underscores instead of dots) > + * > + * This function returns (_type *) pointer to the very first entry of a > + * linker-generated array placed into subsection of .u_boot_list section > + * specified by _section_u argument. > + * > + * Example of usage: > + * > + * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub); > + */ > +#define ll_entry_start(_type, _section_u) \ > + ({ \ > + extern _type _u_boot_list_##_section_u##__start; \ > + _type *_ll_result = &_u_boot_list_##_section_u##__start;\ > + _ll_result; \ > + }) Tricky. I didn't realize this gcc extension existed. > + > +/** > + * ll_entry_count() - Return the number of elements in linker-generated array > + * _type: Data type of the entry > + * _section_u: Subsection of u_boot_list in which this entry is placed > + * (with underscores instead of dots) > + * > + * This function returns the number of elements of a linker-generated array > + * placed into subsection of .u_boot_list section specified by _section_u > + * argument. The result is of an unsigned int type. > + * > + * Example of usage: > + * > + * int i; > + * const unsigned int count = ll_entry_count(struct my_sub_cmd, cmd_sub); > + * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub); > + * for (i = 0; i < count; i++) { > + * printf("Entry %i, x=%i y=%i\n", i, msc->x, msc->y); > + * msc++; > + * } > + */ > +#define ll_entry_count(_type, _section_u) \ > + ({ \ > + extern _type _u_boot_list_##_section_u##__start; \ > + extern _type _u_boot_list_##_section_u##__end; \ > + unsigned int _ll_result = \ > + &_u_boot_list_##_section_u##__end - \ > + &_u_boot_list_##_section_u##__start; \ > + _ll_result; \ > + }) > + > +#endif /* __LINKER_LISTS_H__ */ > -- > 1.7.10.4 > _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot