[U-Boot] [PATCH 1/3] init_func: Add fundamental framework

Marek Vasut
2012-05-03T00:08:24Z

Dear Graeme Russ,

> Signed-off-by: Graeme Russ <graeme.russ@gmail.com>
> ---
> Makefile | 34 ++-
> common/Makefile | 2 +
> config.mk | 2 +
> doc/README.INIT_FUNC | 65 +++
> include/init_func.h | 37 ++
> tools/Makefile | 6 +
> tools/mkinitseq.c | 1512
> ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1657
> insertions(+), 1 deletions(-)
> create mode 100644 doc/README.INIT_FUNC
> create mode 100644 include/init_func.h
> create mode 100644 tools/mkinitseq.c
>

[...]

> --- /dev/null
> +++ b/doc/README.INIT_FUNC
> @@ -0,0 +1,65 @@
> +The INIT_FUNC macro allows initialisation functions (i.e. functions which
> are +executed before the main loop) to be easily added to the init
> sequence +
> +
> +Specifying an Initialisation Function and is Dependencies
> +---------------------------------------------------------
> +The format of the INIT_FUNC macro is:
> +
> +INIT_FUNC(fn, grp, man_reqs, pre_reqs, pst_reqs)
> +
> +fn is the name of the init function to call. This function must have the
> +following prototype:
> +
> +int foo(void);

What if I want to pass some data to such a func ? Clearly, I can think of this
being doable, but extra hard.

> +
> +Each init function must return 0 to indicate success - any other return
> value +indicates failure and the init sequence will stop
> +
> +grp is the name of the group that the init function belongs to. grp may be
> +the same as fn for any individual init function, but between init
> functions, +fn and grp must be unique.
> +
> +The purpose of groups is to allow functions to be grouped together so
> other +functions can specify the group as a whole as a dependency rather
> than having +to list every function in the group in the dependency list
> +
> +man_reqs is a space seperated list of functions or groups that MUST exist
> and +MUST run BEFORE fn
> +
> +pre_reqs is a space seperated list of functions or groups that MAY exist
> and +(if they do) MUST run BEFORE fn
> +
> +pst_reqs is a space seperated list of functions or groups that MAY exist
> and +(if they do) MUST run AFTER fn

What's the point? Can't you create a kind of proxy object that the pst_reqs will
have as a pre_req ?

Maybe you should create this:

INIT_FUNC(fn, grp, prereqs, postreqs) and for each function from prereqs and
postreqs, specify per-function attributes via the GCC __attribute__(())
directive, like if the function must run before something or may run before
something etc?
> +
> +Skipping or Replacing a Function or Group
> +-----------------------------------------
> +Occassionally, a board may provide a completely seperate implementation
> for +an initialisation function that is provided in the common arch, SoC
> or +common code.
> +
> +SKIP_INIT(fn_or_group)
> +
> +After the initialisation function dependencies are calculated, all
> functions +and groups listed in any SKIP_INITs are removed - This may
> result in +dependent functions being removed - It is up to the board code
> developer +to ensure suitable replacements are in place
> +
> +REPLACE_INIT(old_fn_or_group, new_fn_or_group)
> +
> +Like SKIP_INIT but replaces on function with another (or one group with
> +another)
> +
> +Example: In the SoC code yoy may have

Yoy :)

> +
> +INIT_FUNC(init_cpu_f, RESET, , , );
> +
> +In the board code, you may want a slightly tweaked version, so you might
> +have:
> +
> +int my_new_init_cpu_f(void)
> +{
> + ...
> +}
> +REPLACE_INIT(init_cpu_f, my_new_init_cpu_f);
> diff --git a/include/init_func.h b/include/init_func.h
> new file mode 100644
> index 0000000..e4366b8
> --- /dev/null
> +++ b/include/init_func.h
> @@ -0,0 +1,37 @@
> +#ifndef __INIT_FUNC_H__
> +#define __INIT_FUNC_H__
> +
> +/*
> + * The requirements for any new initalization function is simple: it is
> + * a function with no parameters which returns an integer return code,
> + * where 0 means "continue" and != 0 means "fatal error, hang the system"
> + */
> +typedef int (init_fnc_t) (void);
> +
> +extern init_fnc_t *init_sequence_f[];
> +extern init_fnc_t *init_sequence_f_r[];
> +extern init_fnc_t *init_sequence_r[];
> +
> +#ifdef CONFIG_INIT_FUNC
> +#include <linux/compiler.h>
> +
> +#define INIT_FUNC(fn, grp, man_reqs, pre_reqs, pst_reqs) \
> + static const char __init_func_ ## fn[] __used \
> + __attribute__((__section__(".initfuncs"))) = \
> + "(f:" #fn ":" #grp ":" #man_reqs " | " #pre_reqs " | " #pst_reqs ")\n";
> +
> +#define SKIP_INIT(fn_or_group) \
> + static const char __skip_init_ ## fn_or_group[] __used \
> + __attribute__((__section__(".initfuncs"))) = \
> + "(s:" #fn_or_group ")\n";
> +
> +#define REPLACE_INIT(old_fn_or_group, new_fn_or_group) \
> + static const char __replace_init_ ## old_fn_or_group[] __used \
> + __attribute__((__section__(".initfuncs"))) = \
> + "(r:" #old_fn_or_group ":" #new_fn_or_group ")\n";
> +#else
> +#define INIT_FUNC(fn, group, man_reqs, pre_reqs, post_reqs)
> +#define SKIP_INIT(fn_or_group)
> +#define REPLACE_INIT(old_fn_or_group, new_fn_or_group)
> +#endif
> +#endif /* !__INIT_FUNC_H__ */
> diff --git a/tools/Makefile b/tools/Makefile
> index 8993fdd..e6ba6ef 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -68,6 +68,7 @@ BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX)
> BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX)
> BIN_FILES-y += mkenvimage$(SFX)
> BIN_FILES-y += mkimage$(SFX)
> +BIN_FILES-$(CONFIG_INIT_FUNC) += mkinitseq$(SFX)
> BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX)
> BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
> BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
> @@ -95,6 +96,7 @@ NOPED_OBJ_FILES-y += imximage.o
> NOPED_OBJ_FILES-y += omapimage.o
> NOPED_OBJ_FILES-y += mkenvimage.o
> NOPED_OBJ_FILES-y += mkimage.o
> +NOPED_OBJ_FILES-$(CONFIG_INIT_FUNC) += mkinitseq.o
> OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o
> OBJ_FILES-$(CONFIG_MX28) += mxsboot.o
> OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
> @@ -215,6 +217,10 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \
> $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
> $(HOSTSTRIP) $@
>
> +$(obj)mkinitseq$(SFX): $(obj)mkinitseq.o
> + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
> + $(HOSTSTRIP) $@
> +
> $(obj)mk$(BOARD)spl$(SFX): $(obj)mkexynosspl.o
> $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
> $(HOSTSTRIP) $@
> diff --git a/tools/mkinitseq.c b/tools/mkinitseq.c
> new file mode 100644
> index 0000000..b150de4
> --- /dev/null
> +++ b/tools/mkinitseq.c
> @@ -0,0 +1,1512 @@

Ok, this is the worst part. I think this could be reimplemented in shell ;-)

> +/*
> + * (C) Copyright 2012
> + * Graeme Russ <graeme.russ@gmail.com>
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/**
> + * container_of - cast a member of a structure out to the containing
> structure + * @ptr: the pointer to the member.
> + * @type: the type of the container struct this is embedded in.
> + * @member: the name of the member within the struct.
> + *
> + */
> +#define container_of(ptr, type, member) ({ \
> + const typeof( ((type *)0)->member ) *__mptr = (ptr); \
> + (type *)( (char *)__mptr - offsetof(type,member) );})

Don't we already have this defined in uboot ? …