Skip to contentSkip to conversation

initcall revisited - A new idea to discuss

U-Boot Graeme Russ 4 participants 16 messages Jan 2, 2012 – Jan 8, 2012 1 message not in the archive

lore
Share & tools
lore
#0 lore raw

Hi All,

I've been thinking about the renaissance of the arch-independent initialisation sequence that has been generating a somewhat 'warm' discussion lately and had a thought based on a comment passed on by Wolfgang from Detlev:

"basicly what we are trying to solve is a dependency issue: each init function has a list of dependencies (other init steps) that need to be run before"

Which got me to thinking, what if we had an initcall macro which included the dependency information. Imagine this rough example:

	set_reloc_flag_r,
	init_bd_struct_r,
	mem_malloc_init_r,
	cpu_init_r,
	board_early_init_r,
	dram_init,
	interrupt_init,
	timer_init,
	display_banner,
	display_dram_config,

'display_banner' (for the sake of this example) needs 'dram_init' and 'board_early_init_r' while 'timer_init' needs 'interrupt_init'

Now lets imagine a macro which we use thusly:

int display_banner(void)
{
...
}
INITCALL(display_banner, "banner", "dram,board_early")

Which says that the display_banner() function, when completed fulfils the 'banner' dependency, and requires both the 'dram' and 'board_early' dependencies to be fulfilled in order to run

We may also have...

int serial_initialize_r(void)
{
...
}
INITCALL(serial_initialize_r, "serial,console", "environment")

int console_init_r(void)
{
...
}
INITCALL(console_init_r, "console", "serial")

So anything requiring 'console' must happen after both serial_initialize_r and console_init_r (yes, this is a trivial example, but it's the best I can come up with)

So how do we implement it...

If the INITCALL macro can place the parameter data in a separate section in the object file, and this data gets amalgamated into the libraries, we should be able to pull the information out during the build process.

So the build process builds all the libraries, but before the final link, we autogenerate the 'init sequence' array using a fancy 'tool' which scans all the libraries and builds the init sequence in order to satisfy all the dependencies or throws an error if the dependencies cannot be met like:

'console_init_r' requires 'serial' but there are no 'serial' init functions

or

'circular reference - 'serial' requires 'console' requires 'serial'

etc.

Thoughts?

Regards,

Graeme

#1 lore raw

Dear Graeme Russ,

Quoted 3 lines · In message <[email protected]> you wrote:

Which got me to thinking, what if we had an initcall macro which included the dependency information. Imagine this rough example:

...

Quoted 5 lines

INITCALL(display_banner, "banner", "dram,board_early")

Which says that the display_banner() function, when completed fulfils the 'banner' dependency, and requires both the 'dram' and 'board_early' dependencies to be fulfilled in order to run

Sounds great!

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Our OS who art in CPU, UNIX be thy name.
Thy programs run, thy syscalls done,
In kernel as it is in user!
#2 lore raw

Hi Wolfgang,

Quoted 6 lines · Wolfgang Denk

Dear Graeme Russ,

Quoted 3 lines · In message <[email protected]> you wrote:

Which got me to thinking, what if we had an initcall macro which included the dependency information. Imagine this rough example:

Quoted 8 lines

...

Quoted 5 lines

INITCALL(display_banner, "banner", "dram,board_early")

Which says that the display_banner() function, when completed fulfils the 'banner' dependency, and requires both the 'dram' and 'board_early' dependencies to be fulfilled in order to run

Sounds great!

OK, I think I can do this...

#define INIT_FUNC(fn, stage, reqs, prereqs, postreqs) \
	static const char *__initfunc_ ## fn __used \
	__attribute__((__section__(".initfuncs"))) = \
	#stage ":" #fn ":" #reqs ":" #prereqs ":" #postreqs

'postreq' are requisite functions that the given function must be run before (USB init priot to console if using a USB serial dongle for example)

Then:

INIT_FUNC(cpu_init_f, f, "fred", "blah", "foo");

Generates the string:
f:cpu_init_f:"fred":"blah":"foo"

and we can parse each of the elf archives to obtain a list of string pointers from the .initfuncs, extract the strings and process them to generate the init arrays

and add:

	/DISCARD/ : { *(.initfuncs*) }

to the linker script to throw away the strings

It's a tad ugly under the hood, but the output will be very clean

Does this sound like a plan?

Regards,

Graeme

#3 lore raw

Dear Graeme,

Quoted 32 lines · In message <[email protected]> you wrote:
Quoted 8 lines
Quoted 6 lines

INITCALL(display_banner, "banner", "dram,board_early")

Which says that the display_banner() function, when completed fulfils the 'banner' dependency, and requires both the 'dram' and 'board_early' dependencies to be fulfilled in order to run

Sounds great!

OK, I think I can do this...

#define INIT_FUNC(fn, stage, reqs, prereqs, postreqs) \
	static const char *__initfunc_ ## fn __used \
	__attribute__((__section__(".initfuncs"))) = \
	#stage ":" #fn ":" #reqs ":" #prereqs ":" #postreqs

'postreq' are requisite functions that the given function must be run before (USB init priot to console if using a USB serial dongle for example)

Then:

INIT_FUNC(cpu_init_f, f, "fred", "blah", "foo");

Generates the string:
f:cpu_init_f:"fred":"blah":"foo"

and we can parse each of the elf archives to obtain a list of string pointers from the .initfuncs, extract the strings and process them to generate the init arrays

and add:

Quoted 7 lines
	/DISCARD/ : { *(.initfuncs*) }

to the linker script to throw away the strings

It's a tad ugly under the hood, but the output will be very clean

Does this sound like a plan?

Yes. Looks good to me.

One thing comes to mind: it would be nice if we can find a way that the INIT_FUNC definitions behave similar to "weak" functions - if an init_func can be redefined / overwritten / modified by board specific code we eventually have a very nice way to get rid of the related #ifdef's.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"Life sucks, but it's better than the alternative."
- Peter da Silva
#14 lore raw
In reply to Graeme Russ

Hi Graham,

Quoted 41 lines · Graeme Russ

Hi Wolfgang,

Quoted 6 lines · Wolfgang Denk

Dear Graeme Russ,

Quoted 3 lines · In message <[email protected]> you wrote:

Which got me to thinking, what if we had an initcall macro which included the dependency information. Imagine this rough example:

Quoted 8 lines

...

Quoted 5 lines

INITCALL(display_banner, "banner", "dram,board_early")

Which says that the display_banner() function, when completed fulfils the 'banner' dependency, and requires both the 'dram' and 'board_early' dependencies to be fulfilled in order to run

Sounds great!

OK, I think I can do this...

#define INIT_FUNC(fn, stage, reqs, prereqs, postreqs) \
? ? ? ?static const char *__initfunc_ ## fn __used \
? ? ? ?__attribute__((__section__(".initfuncs"))) = \
? ? ? ?#stage ":" #fn ":" #reqs ":" #prereqs ":" #postreqs

'postreq' are requisite functions that the given function must be run before (USB init priot to console if using a USB serial dongle for example)

Then:

INIT_FUNC(cpu_init_f, f, "fred", "blah", "foo");

Generates the string:
f:cpu_init_f:"fred":"blah":"foo"

and we can parse each of the elf archives to obtain a list of string pointers from the .initfuncs, extract the strings and process them to generate the init arrays

and add:

Quoted 7 lines

? ? ? ?/DISCARD/ : { *(.initfuncs*) }

to the linker script to throw away the strings

It's a tad ugly under the hood, but the output will be very clean

Does this sound like a plan?

Good with me - will be very interesting to see where this takes us.

I have been thinking if there is a way we can avoid the post-processing perhaps by specifying two function parameters to the macro (the init function to call and its prerequisite) and having the initcall code sort the list before starting. We could have dummy functions to mark particular stages of interest to boards. But it can't deal with adding a new function as a prerequisite of an existing one without perhaps a third parameter. I haven't looked at the algorithm either...

But I wonder if it would be possible for your macro to generate a table which includes the init function as well as the string? That way we get a compile warning and link error if the function doesn't exist.

Regards,
Simon

Quoted 4 lines

Regards,

Graeme

#4 lore raw
In reply to Wolfgang Denk

Hi Wolfgang,

Quoted 4 lines · Wolfgang Denk

Dear Graeme,

Quoted 1 line · In message <[email protected]> you wrote:

[snip]

Quoted 5 lines

One thing comes to mind: it would be nice if we can find a way that the INIT_FUNC definitions behave similar to "weak" functions - if an init_func can be redefined / overwritten / modified by board specific code we eventually have a very nice way to get rid of the related #ifdef's.

Well a lot of the #ifdefs will disappear when the INIT_FUNC macros gets migrated the the corresponding source files as the Makefile logic will take care of things for us

I do have in the back of my mind the 'what if' case of the dependencies needing to be different between two arches or boards, but I really can't think of a case where this would be the case. I added the 'post-req' to the macro to allow an init function to be inserted before an existing function which I think will be the most likely case (initialising on-board hardware such as an FPGA prior to timer initialisation for example)

We'll see how it pans out

Regards,

Graeme

#15 lore raw
In reply to Simon Glass

Dear Simon Glass,

Quoted 5 lines · In message <CAPnjgZ3aOyvYPA93ecbMyqhCaaZcBPhfcYhXYYa1ax+9_uEojw@mail.gmail.com>…

I have been thinking if there is a way we can avoid the post-processing perhaps by specifying two function parameters to the macro (the init function to call and its prerequisite) and having the initcall code sort the list before starting. We could have dummy

You mean sort at runtime?

NAK. all this must be done when building, i. e. at compile time.

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"The combination of a number of things to make existence worthwhile."
"Yes, the philosophy of 'none,' meaning 'all.'"
	-- Spock and Lincoln, "The Savage Curtain", stardate 5906.4
#16 lore raw

Hi Wolfgang,

Quoted 4 lines · Wolfgang Denk

Dear Simon Glass,

Quoted 1 line · In message <CAPnjgZ3aOyvYPA93ecbMyqhCaaZcBPhfcYhXYYa1ax+9_uEojw@mail.gmail.com>…
Quoted 8 lines
Quoted 4 lines

I have been thinking if there is a way we can avoid the post-processing perhaps by specifying two function parameters to the macro (the init function to call and its prerequisite) and having the initcall code sort the list before starting. We could have dummy

You mean sort at runtime?

NAK. ?all this must be done when building, i. e. at compile time.

Yes that's what I meant. It is more flexible to do this at build time if we are happy with the additional build step. OK.

Regards,
Simon

Quoted 12 lines

Best regards,

Wolfgang Denk

--
DENX Software Engineering GmbH, ? ? MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de "The combination of a number of things to make existence worthwhile." "Yes, the philosophy of 'none,' meaning 'all.'"
? ? ? ?-- Spock and Lincoln, "The Savage Curtain", stardate 5906.4

#5 lore raw
In reply to Wolfgang Denk

Hi Wolfgang,

Quoted 4 lines · Wolfgang Denk

Dear Graeme,

Quoted 1 line · In message <[email protected]> you wrote:

[snip]

Quoted 19 lines
Quoted 11 lines

INIT_FUNC(cpu_init_f, f, "fred", "blah", "foo");

Generates the string:
f:cpu_init_f:"fred":"blah":"foo"

and we can parse each of the elf archives to obtain a list of string pointers from the .initfuncs, extract the strings and process them to generate the init arrays

and add:

Quoted 7 lines
      /DISCARD/ : { *(.initfuncs*) }

to the linker script to throw away the strings

It's a tad ugly under the hood, but the output will be very clean

Does this sound like a plan?

Quoted 7 lines

Yes. Looks good to me.

One thing comes to mind: it would be nice if we can find a way that the INIT_FUNC definitions behave similar to "weak" functions - if an init_func can be redefined / overwritten / modified by board specific code we eventually have a very nice way to get rid of the related #ifdef's.

I have a thought on this. How about a SKIP_INIT macro. Here's the idea using SDRAM as an example:

At the arch level you may have

INIT_FUNC(sdram_init, f, "sdram", "console","")

so sdram_init sets the "sdram" requisite and must be done after all "console" requisites have been completed.

Now if a SoC or board has an init that must be done before SDRAM:

INIT_FUNC(pre_sdram_init, f, "pre_sdram", "", "sdram")

So this sets the pre_sdram requisite, requires no other initialisation before running and must happen before and "sdram" init functions are run

Now lets say the Soc or board has a unique sdram init function that overrides the arch's sdram init. We could just use weak functions and allow the SoC or board to override sdram_init. But what if the SoC or board has additional pre-requisite (or post-requisite) init requirements?

So in the SoC or board file:

SKIP_INIT(sdram)
INIT_FUNC(board_sdram_init, f, "board_sdram","pre_sdram,vreg,console", "")

Using "board_sdram" versus "sdram_init" is cricital:

The init sequence build tool will first create the entire init sequence including the functions marked as "sdram" and "board_sdram". But after building the arrays, it will strip out all the functions marked as "sdram" init functions. The reason the entire list has to be build first is so the functions that rely on "sdram" can be added without unmet prerequisite errors.

Of course, if you use SKIP_INIT(foo), you need to make sure that any replacement INIT_FUNC will do everything foo did to make your board work.

Interestingly, this allows the following:

INIT_FUNC(calc_relocation, fr, "calc_reloc", "sdram", "") INIT_FUNC(copy_uboot_to_ram, fr, "copy_to_ram", "calc_relocation", "") INIT_FUNC(do_elf_reloc_adjusments, fr, "elf_reloc", "copy_to_ram", "") INIT_FUNC(clear_bss, fr, "clear_bss", "calc_reloc", "")

#ifdef CONFIG_SYS_SKIP_RELOCATION
SKIP_INIT(calc_reloc)
SKIP_INIT(copy_to_ram)
SKIP_INIT(elf_reloc)
#endif

So if CONFIG_SYS_SKIP_RELOCATION is defined, relocation is not performed, but clear_bss still is

Regards,

Graeme

#6 lore raw

Hi Graham,

Quoted 37 lines · Graeme Russ

Hi Wolfgang,

Quoted 4 lines · Wolfgang Denk

Dear Graeme,

Quoted 1 line · In message <[email protected]> you wrote:

[snip]

Quoted 19 lines
Quoted 11 lines

INIT_FUNC(cpu_init_f, f, "fred", "blah", "foo");

Generates the string:
f:cpu_init_f:"fred":"blah":"foo"

and we can parse each of the elf archives to obtain a list of string pointers from the .initfuncs, extract the strings and process them to generate the init arrays

and add:

Quoted 7 lines

? ? ? /DISCARD/ : { *(.initfuncs*) }

to the linker script to throw away the strings

It's a tad ugly under the hood, but the output will be very clean

Does this sound like a plan?

Quoted 7 lines

Yes. ?Looks good to me.

One thing comes to mind: it would be nice if we can find a way that the INIT_FUNC definitions behave similar to "weak" functions - if an init_func can be redefined / overwritten / modified by board specific code we eventually have a very nice way to get rid of the related #ifdef's.

Quoted 6 lines

I have a thought on this. How about a SKIP_INIT macro. Here's the idea using SDRAM as an example:

At the arch level you may have

INIT_FUNC(sdram_init, f, "sdram", "console","")

Gosh this email took a few readings :-)

Can we get rid of the 'f' parameter? If we invent a prerequisite called 'relocated' or something like that, to act as a barrier, then maybe the order can be defined just like any other function which depends on being before or after something?

Quoted 40 lines

so sdram_init sets the "sdram" requisite and must be done after all "console" requisites have been completed.

Now if a SoC or board has an init that must be done before SDRAM:

INIT_FUNC(pre_sdram_init, f, "pre_sdram", "", "sdram")

So this sets the pre_sdram requisite, requires no other initialisation before running and must happen before and "sdram" init functions are run

Now lets say the Soc or board has a unique sdram init function that overrides the arch's sdram init. We could just use weak functions and allow the SoC or board to override sdram_init. But what if the SoC or board has additional pre-requisite (or post-requisite) init requirements?

So in the SoC or board file:

SKIP_INIT(sdram)
INIT_FUNC(board_sdram_init, f, "board_sdram","pre_sdram,vreg,console", "")

Using "board_sdram" versus "sdram_init" is cricital:

The init sequence build tool will first create the entire init sequence including the functions marked as "sdram" and "board_sdram". But after building the arrays, it will strip out all the functions marked as "sdram" init functions. The reason the entire list has to be build first is so the functions that rely on "sdram" can be added without unmet prerequisite errors.

Of course, if you use SKIP_INIT(foo), you need to make sure that any replacement INIT_FUNC will do everything foo did to make your board work.

Interestingly, this allows the following:

INIT_FUNC(calc_relocation, fr, "calc_reloc", "sdram", "") INIT_FUNC(copy_uboot_to_ram, fr, "copy_to_ram", "calc_relocation", "") INIT_FUNC(do_elf_reloc_adjusments, fr, "elf_reloc", "copy_to_ram", "") INIT_FUNC(clear_bss, fr, "clear_bss", "calc_reloc", "")

Quoted 9 lines

#ifdef CONFIG_SYS_SKIP_RELOCATION
SKIP_INIT(calc_reloc)
SKIP_INIT(copy_to_ram)
SKIP_INIT(elf_reloc)
#endif

So if CONFIG_SYS_SKIP_RELOCATION is defined, relocation is not performed, but clear_bss still is

I wonder what happens when you skip something - does it substitute for any pre/post-requisites that the skipped item had? Or would that be illegal?

I can see plenty of opportunity for confusion, but if the tool is friendly enough, then this could solve a lot of the override problems. In your particular example it feels like it would be easier to just make the INIT_FUNC conditional on an config using #ifdef (horror!), or perhaps yet another parameter(!).

Or we could just put those relocation functions in their own file and have it omitted from the build by the Makefile in the case where CONFIG_SYS_SKIP_RELOCATION is defined.

And if we want wanting to replace a generic function with a board-specific one, why not just something like:

INIT_OVERRIDE(new_func, old_func)

Anyway, it sounds very promising.

Regards,
Simon

Quoted 3 lines

Regards,

Graeme

#7 lore raw

Hi Simon,

Quoted 11 lines · Simon Glass

Hi Graham,

Quoted 8 lines · Graeme Russ

Hi Wolfgang,

Quoted 4 lines · Wolfgang Denk

Dear Graeme,

Quoted 1 line · In message <[email protected]> you wrote:

[snip]

Quoted 12 lines
Quoted 12 lines
Quoted 6 lines

One thing comes to mind: it would be nice if we can find a way that the INIT_FUNC definitions behave similar to "weak" functions - if an init_func can be redefined / overwritten / modified by board specific code we eventually have a very nice way to get rid of the related #ifdef's.

I have a thought on this. How about a SKIP_INIT macro. Here's the idea using SDRAM as an example:

At the arch level you may have

Quoted 8 lines
Quoted 1 line

INIT_FUNC(sdram_init, f, "sdram", "console","")

Gosh this email took a few readings :-)

Can we get rid of the 'f' parameter? If we invent a prerequisite called 'relocated' or something like that, to act as a barrier, then maybe the order can be defined just like any other function which depends on being before or after something?

Well I kind of like see that a particular init function is explicitly a pre- or post- relocation function. But yes, having barrier pre-requisites would achieve the same effect.

Quoted 45 lines
Quoted 45 lines

so sdram_init sets the "sdram" requisite and must be done after all "console" requisites have been completed.

Now if a SoC or board has an init that must be done before SDRAM:

INIT_FUNC(pre_sdram_init, f, "pre_sdram", "", "sdram")

So this sets the pre_sdram requisite, requires no other initialisation before running and must happen before and "sdram" init functions are run

Now lets say the Soc or board has a unique sdram init function that overrides the arch's sdram init. We could just use weak functions and allow the SoC or board to override sdram_init. But what if the SoC or board has additional pre-requisite (or post-requisite) init requirements?

So in the SoC or board file:

SKIP_INIT(sdram)
INIT_FUNC(board_sdram_init, f, "board_sdram","pre_sdram,vreg,console", "")

Using "board_sdram" versus "sdram_init" is cricital:

The init sequence build tool will first create the entire init sequence including the functions marked as "sdram" and "board_sdram". But after building the arrays, it will strip out all the functions marked as "sdram" init functions. The reason the entire list has to be build first is so the functions that rely on "sdram" can be added without unmet prerequisite errors.

Of course, if you use SKIP_INIT(foo), you need to make sure that any replacement INIT_FUNC will do everything foo did to make your board work.

Interestingly, this allows the following:

INIT_FUNC(calc_relocation, fr, "calc_reloc", "sdram", "") INIT_FUNC(copy_uboot_to_ram, fr, "copy_to_ram", "calc_relocation", "") INIT_FUNC(do_elf_reloc_adjusments, fr, "elf_reloc", "copy_to_ram", "") INIT_FUNC(clear_bss, fr, "clear_bss", "calc_reloc", "")

#ifdef CONFIG_SYS_SKIP_RELOCATION
SKIP_INIT(calc_reloc)
SKIP_INIT(copy_to_ram)
SKIP_INIT(elf_reloc)
#endif

Quoted 7 lines
Quoted 3 lines

So if CONFIG_SYS_SKIP_RELOCATION is defined, relocation is not performed, but clear_bss still is

I wonder what happens when you skip something - does it substitute for any pre/post-requisites that the skipped item had? Or would that be illegal?

SKIP_INIT(foo) simply removes all 'foo' init functions from the list _after_ the list has been created - If this breaks dependencies that's your problem ;). It is up to you as the 'skipper' to make sure that you add init functions to allow things to still work

Quoted 5 lines

I can see plenty of opportunity for confusion, but if the tool is friendly enough, then this could solve a lot of the override problems. In your particular example it feels like it would be easier to just make the INIT_FUNC conditional on an config using #ifdef (horror!), or perhaps yet another parameter(!)

The idea behind this all is that we do not know today what we will need tomorrow. Our biggest issue right now is that if a board needs to tweak the init sequence, it needs to touch arch/foo/board.c and hence introduces the potential to break working boards.

With this proposal, if a board wants to entirely re-write the init sequence, it can add a whole bunch of SKIP_INIT(blah) and then add it's own INIT_FUNC(init_func, "myboard_bar"...) and nobody else will be the wiser as to what is going on. The problem the is if the arch adds a new init step, it may not be covered by the skip list by that board - tough, lesson learn't for being so esoteric ;)

Quoted 3 lines

Or we could just put those relocation functions in their own file and have it omitted from the build by the Makefile in the case where CONFIG_SYS_SKIP_RELOCATION is defined.

Exactly. My example was a poor practical example, but it demonstrated a point. Obviously, clear_bss() does not belong with the relocation code

Quoted 4 lines

And if we want wanting to replace a generic function with a board-specific one, why not just something like:

INIT_OVERRIDE(new_func, old_func)

In such circumstances, we still have weak functions. I see no reason to not keep on using weak functions for init functions that have well defined override scenarios (cache initialisation is a prime example, so is timer initialisation)

Quoted 1 line

Anyway, it sounds very promising.

Yes, it's a lot better than my original proposal :)

Regards,

Graeme

#8 lore raw

Hi,

Quoted 91 lines · Graeme Russ

Hi Simon,

Quoted 11 lines · Simon Glass

Hi Graham,

Quoted 8 lines · Graeme Russ

Hi Wolfgang,

Quoted 4 lines · Wolfgang Denk

Dear Graeme,

Quoted 1 line · In message <[email protected]> you wrote:

[snip]

Quoted 12 lines
Quoted 12 lines
Quoted 6 lines

One thing comes to mind: it would be nice if we can find a way that the INIT_FUNC definitions behave similar to "weak" functions - if an init_func can be redefined / overwritten / modified by board specific code we eventually have a very nice way to get rid of the related #ifdef's.

I have a thought on this. How about a SKIP_INIT macro. Here's the idea using SDRAM as an example:

At the arch level you may have

Quoted 8 lines
Quoted 1 line

INIT_FUNC(sdram_init, f, "sdram", "console","")

Gosh this email took a few readings :-)

Can we get rid of the 'f' parameter? If we invent a prerequisite called 'relocated' or something like that, to act as a barrier, then maybe the order can be defined just like any other function which depends on being before or after something?

Well I kind of like see that a particular init function is explicitly a pre- or post- relocation function. But yes, having barrier pre-requisites would achieve the same effect.

Quoted 49 lines
Quoted 48 lines

so sdram_init sets the "sdram" requisite and must be done after all "console" requisites have been completed.

Now if a SoC or board has an init that must be done before SDRAM:

INIT_FUNC(pre_sdram_init, f, "pre_sdram", "", "sdram")

So this sets the pre_sdram requisite, requires no other initialisation before running and must happen before and "sdram" init functions are run

Now lets say the Soc or board has a unique sdram init function that overrides the arch's sdram init. We could just use weak functions and allow the SoC or board to override sdram_init. But what if the SoC or board has additional pre-requisite (or post-requisite) init requirements?

So in the SoC or board file:

SKIP_INIT(sdram)
INIT_FUNC(board_sdram_init, f, "board_sdram","pre_sdram,vreg,console", "")

Using "board_sdram" versus "sdram_init" is cricital:

The init sequence build tool will first create the entire init sequence including the functions marked as "sdram" and "board_sdram". But after building the arrays, it will strip out all the functions marked as "sdram" init functions. The reason the entire list has to be build first is so the functions that rely on "sdram" can be added without unmet prerequisite errors.

Of course, if you use SKIP_INIT(foo), you need to make sure that any replacement INIT_FUNC will do everything foo did to make your board work.

Interestingly, this allows the following:

INIT_FUNC(calc_relocation, fr, "calc_reloc", "sdram", "") INIT_FUNC(copy_uboot_to_ram, fr, "copy_to_ram", "calc_relocation", "") INIT_FUNC(do_elf_reloc_adjusments, fr, "elf_reloc", "copy_to_ram", "") INIT_FUNC(clear_bss, fr, "clear_bss", "calc_reloc", "")

#ifdef CONFIG_SYS_SKIP_RELOCATION
SKIP_INIT(calc_reloc)
SKIP_INIT(copy_to_ram)
SKIP_INIT(elf_reloc)
#endif

So if CONFIG_SYS_SKIP_RELOCATION is defined, relocation is not performed, but clear_bss still is

Quoted 8 lines
Quoted 3 lines

I wonder what happens when you skip something - does it substitute for any pre/post-requisites that the skipped item had? Or would that be illegal?

SKIP_INIT(foo) simply removes all 'foo' init functions from the list _after_ the list has been created - If this breaks dependencies that's your problem ;). It is up to you as the 'skipper' to make sure that you add init functions to allow things to still work

Won't this lead to lots of code duplication across all boards, archs. So, tomorrow someone else will send a patch removing duplicate and merging it to a common place.

Why don't start it in 1st place.

Quoted 12 lines
Quoted 6 lines

I can see plenty of opportunity for confusion, but if the tool is friendly enough, then this could solve a lot of the override problems. In your particular example it feels like it would be easier to just make the INIT_FUNC conditional on an config using #ifdef (horror!), or perhaps yet another parameter(!)

The idea behind this all is that we do not know today what we will need tomorrow. Our biggest issue right now is that if a board needs to tweak the init sequence, it needs to touch arch/foo/board.c and hence introduces the potential to break working boards.

Quoted 7 lines

With this proposal, if a board wants to entirely re-write the init sequence, it can add a whole bunch of SKIP_INIT(blah) and then add it's own INIT_FUNC(init_func, "myboard_bar"...) and nobody else will be the wiser as to what is going on. The problem the is if the arch adds a new init step, it may not be covered by the skip list by that board - tough, lesson learn't for being so esoteric ;)

So, every board, even under same arch, needs to define its own *complete-set* of INIT_CALL api's. I am dreaming about a lot of MB getting added to u-boot src.

Just a thought. Why don't split it to ARCH_INIT, BOARD_INIT,.

Quoted 21 lines
Quoted 3 lines

Or we could just put those relocation functions in their own file and have it omitted from the build by the Makefile in the case where CONFIG_SYS_SKIP_RELOCATION is defined.

Exactly. My example was a poor practical example, but it demonstrated a point. Obviously, clear_bss() does not belong with the relocation code

Quoted 4 lines

And if we want wanting to replace a generic function with a board-specific one, why not just something like:

INIT_OVERRIDE(new_func, old_func)

In such circumstances, we still have weak functions. I see no reason to not keep on using weak functions for init functions that have well defined override scenarios (cache initialisation is a prime example, so is timer initialisation)

Quoted 1 line

Anyway, it sounds very promising.

Yes, it's a lot better than my original proposal :)

Quoted 8 lines

Regards,

Graeme
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Regards,
Gururaja

#13 lore raw
In reply to Graeme Russ

Dear Graeme Russ,

Quoted 9 lines · In message <CALButCLVdsiGMpwt04+-aQPDVJ_zx9ZZkbXH+ifcSxDxaBdv3A@mail.gmail.com>…
Quoted 5 lines

Can we get rid of the 'f' parameter? If we invent a prerequisite called 'relocated' or something like that, to act as a barrier, then maybe the order can be defined just like any other function which depends on being before or after something?

Well I kind of like see that a particular init function is explicitly a pre- or post- relocation function. But yes, having barrier pre-requisites would achieve the same effect.

I like the idea of having general synchronization (or barrier) entries, instead of pre- or post relocation, especially when considering the case of different configurations with or without SPL code or with externel pre-loaders or ...

Quoted 8 lines
Quoted 3 lines

I wonder what happens when you skip something - does it substitute for any pre/post-requisites that the skipped item had? Or would that be illegal?

SKIP_INIT(foo) simply removes all 'foo' init functions from the list _after_ the list has been created - If this breaks dependencies that's your problem ;). It is up to you as the 'skipper' to make sure that you add init functions to allow things to still work

Isn't that always the case? The functionsprovided by the user must perform their task - the dependency checking can only test the exitence of the function that claims to provide a specific property, but it cannot check if it actually does so.

Quoted 6 lines

With this proposal, if a board wants to entirely re-write the init sequence, it can add a whole bunch of SKIP_INIT(blah) and then add it's own INIT_FUNC(init_func, "myboard_bar"...) and nobody else will be the wiser as to what is going on. The problem the is if the arch adds a new init step, it may not be covered by the skip list by that board - tough, lesson learn't for being so esoteric ;)

We do something similar to the implemetnation of CONFIG_CMD_ and offer a way not to include the default init list at all.

Quoted 3 lines
Quoted 1 line

Anyway, it sounds very promising.

Yes, it's a lot better than my original proposal :)

It's fun to see this grow.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A fail-safe circuit will destroy others.                 -- Klipstein
#9 lore raw
In reply to Hebbar

Dear "Hebbar, Gururaja",

Quoted 4 lines · In message <[email protected]> you wrote:
Quoted 4 lines

Well I kind of like see that a particular init function is explicitly a pre- or post- relocation function. But yes, having barrier pre-requisites would achieve the same effect.

This point of vew is too restricted. Think of boards that use SPL, or where a rom boot loader loads U-Boot directory to RAM, or ...

Quoted 8 lines
Quoted 4 lines

SKIP_INIT(foo) simply removes all 'foo' init functions from the list _after_ the list has been created - If this breaks dependencies that's your problem ;). It is up to you as the 'skipper' to make sure that you add init functions to allow things to still work

Won't this lead to lots of code duplication across all boards, archs. So, tomorrow someone else will send a patch removing duplicate and merging it to a common place.

I don't see why that would happen? I see no intention nor any need for duplicated code.

Quoted 3 lines

So, every board, even under same arch, needs to define its own *complete-set* of INIT_CALL api's. I am dreaming about a lot of MB getting added to u-boot src.

What makes you think so?

Quoted 1 line

Just a thought. Why don't split it to ARCH_INIT, BOARD_INIT,.

Because it's not such an easy split. You can define such groups, like arch, SoC, board family, board. But you cannot initialize the system in such grous - instead, initialization will jump around heavily between these groups, in a sequence that needs to be well defined, and that is often diofferent from board to board.

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
When properly administered, vacations do not  diminish  productivity:
for every week you're away and get nothing done, there's another when
your boss is away and you get twice as much done.  -- Daniel B. Luten
#11 lore raw
In reply to a message not in the archive

Hi Gururaja,

Quoted 31 lines · Gururaja
Quoted 2 lines · Wolfgang Denk

Dear "Hebbar, Gururaja",

[snip]

Quoted 8 lines
Quoted 7 lines
Quoted 3 lines

_after_ the list has been created - If this breaks dependencies that's your problem ;). It is up to you as the 'skipper' to make sure that you add init functions to allow things to still work

Won't this lead to lots of code duplication across all boards, archs. So, tomorrow someone else will send a patch removing duplicate and merging it to a common place.

Quoted 8 lines

I don't see why that would happen? ?I see no intention nor any need for duplicated code.

Quoted 3 lines

So, every board, even under same arch, needs to define its own *complete-set* of INIT_CALL api's. I am dreaming about a lot of MB getting added to u-boot src.

What makes you think so?

As mentioned before, the INIT_CALL code is to be added to each board file for each arch, soc.
I was speaking of actual C Code. Every board needs serial, console, i2c and many other common code. Wont they increase u-boot source size (in actual c code size).
Every Board Maintainer will have almost same "x-lines-added" in the U-Boot release statics/summary page.

Quoted 1 line

Kindly correct me if I am wrong.

I hope I understand you correctly. The idea is that the init list is specified for the architecture (or hopefully soon for the whole of U-Boot). Boards only need to mess with it if they want to add / remove something. Hopefully most boards won't do much at all with the init sequence.

Quoted 10 lines
Quoted 9 lines
Quoted 3 lines

Just a thought. Why don't split it to ARCH_INIT, BOARD_INIT,.

Because it's not such an easy split. You can define such groups, like arch, SoC, board family, board. ?But you cannot initialize the system in such grous - instead, initialization will jump around heavily between these groups, in a sequence that needs to be well defined, and that is often diofferent from board to board.

Quoted 4 lines

Correct. Then Board maintainer will mention ARCH_INIT, SKIP_ARCH_INIT, BOARD_INIT ...
By this way, Board maintainer can make use of common init calls between ARCHs, SOCs and BOARDs.

See above, which hopefully contains what you need.

At the moment we have things like arch_cpu_init() and the like to do common init for an arch, soc. I think you are saying that the arch code should be able to add things to the init list without every board for that arch doing it explicitly. If so, then that's exactly what Graeme's idea should achieve. The arch code will have several INITCALL() steps to achieve this. It actually lends itself quite well to this requirement. Any file can put an INITCALL() in the sequence and the collection tool / linker tidy things up at the end. The boards should only have to worry about what they want to add/change for their own narrow purposes.

Regards,
Simon

Quoted 10 lines
Quoted 6 lines

Best regards,

Wolfgang Denk

Regards,
Gururaja

#12 lore raw

Hi Simon,

Quoted 35 lines · Simon Glass

Hi Gururaja,

Quoted 31 lines · Gururaja
Quoted 2 lines · Wolfgang Denk

Dear "Hebbar, Gururaja",

[snip]

Quoted 8 lines
Quoted 7 lines
Quoted 3 lines

_after_ the list has been created - If this breaks dependencies that's your problem ;). It is up to you as the 'skipper' to make sure that you add init functions to allow things to still work

Won't this lead to lots of code duplication across all boards, archs. So, tomorrow someone else will send a patch removing duplicate and merging it to a common place.

Quoted 8 lines

I don't see why that would happen? I see no intention nor any need for duplicated code.

Quoted 3 lines

So, every board, even under same arch, needs to define its own *complete-set* of INIT_CALL api's. I am dreaming about a lot of MB getting added to u-boot src.

What makes you think so?

As mentioned before, the INIT_CALL code is to be added to each board file for each arch, soc.
I was speaking of actual C Code. Every board needs serial, console, i2c and many other common code. Wont they increase u-boot source size (in actual c code size).
Every Board Maintainer will have almost same "x-lines-added" in the U-Boot release statics/summary page.

Quoted 7 lines
Quoted 1 line

Kindly correct me if I am wrong.

I hope I understand you correctly. The idea is that the init list is specified for the architecture (or hopefully soon for the whole of U-Boot). Boards only need to mess with it if they want to add / remove something. Hopefully most boards won't do much at all with the init sequence.

Using the proposal, there is no 'architecture init sequence' like there is now. Instead, everything that needs to be initialised before the main loop simply states that fact be adding an instance of the INIT_FUNC macro which specifies:
- The name of the function to be called
- The type of init being performed (console, sdram, fpga etc)
- What type(s) of inits need to be performed before the named function can be called
- What type(s) of inits the named function needs to be called before

A board can freely insert additional init steps by adding INIT_CALLs

A board can override a 'standard' init step by adding SKIP_INIT and the replacement INIT_CALL

Quoted 15 lines
Quoted 10 lines
Quoted 9 lines
Quoted 3 lines

Just a thought. Why don't split it to ARCH_INIT, BOARD_INIT,.

Because it's not such an easy split. You can define such groups, like arch, SoC, board family, board. But you cannot initialize the system in such grous - instead, initialization will jump around heavily between these groups, in a sequence that needs to be well defined, and that is often diofferent from board to board.

Quoted 4 lines

Correct. Then Board maintainer will mention ARCH_INIT, SKIP_ARCH_INIT, BOARD_INIT ...
By this way, Board maintainer can make use of common init calls between ARCHs, SOCs and BOARDs.

Quoted 6 lines

See above, which hopefully contains what you need.

At the moment we have things like arch_cpu_init() and the like to do common init for an arch, soc. I think you are saying that the arch code should be able to add things to the init list without every board for that arch doing it explicitly. If so, then that's exactly what

Well, the arch code already can thanks to the init sequence being encoded into arch/foo/lib/board.c

The problem is what if the CPU needs additional init, or the SoC, or a single board that no other CPU/SoC/board under that arch needs? At the moment, the solution is a combination of over-rideable weak functions and #ifdefs

Quoted 2 lines

Graeme's idea should achieve. The arch code will have several INITCALL() steps to achieve this. It actually lends itself quite well

Not only the arch code, but any code that needs to initialise something prior to entering the main loop - This can include the arch, SoC, CPU, board, chipset, drivers, etc...

So long term, we should see the mess that is the Ethernet and serial driver init code cleaned up because each driver can simply add an INIT_FUNC

Quoted 4 lines

to this requirement. Any file can put an INITCALL() in the sequence and the collection tool / linker tidy things up at the end. The boards should only have to worry about what they want to add/change for their own narrow purposes.

Exactly :)

Regards,

Graeme