[U-Boot] [PATCH 2/3 V2] common: Implement support for linker-generated arrays

Marek Vasut marex at denx.de
Tue Sep 25 18:11:59 CEST 2012


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 <marex at denx.de>
Cc: Joe Hershberger <joe.hershberger at gmail.com>
Cc: Mike Frysinger <vapier at gentoo.org>
---
 include/linker_lists.h |  124 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)
 create mode 100644 include/linker_lists.h

V2: Don't define the variable twice in ll_entry_declare()

diff --git a/include/linker_lists.h b/include/linker_lists.h
new file mode 100644
index 0000000..27ae40b
--- /dev/null
+++ b/include/linker_lists.h
@@ -0,0 +1,124 @@
+/*
+ * include/linker_lists.h
+ *
+ * Implementation of linker-generated arrays
+ *
+ * Copyright (C) 2012 Marek Vasut <marex at 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)))
+
+/**
+ * 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;						\
+	})
+
+/**
+ * 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



More information about the U-Boot mailing list