[U-Boot] [RFC PATCH 0/19] Create generic board init and move ARM and x86 to it

This series creates a generic board.c implementation which contains the essential functions of the various arch/xxx/lib/board.c files.
What is the motivation for this change?
1. There is a lot of repeated code in the board.c files. Any change to things like setting up the baud rate requires a change in 10 separate places.
2. Since there are 10 separate files, adding a new feature which requires initialisation is painful since it must be independently added in 10 places.
3. As time goes by the architectures naturely diverge since there is limited pressure to compare features or even CONFIG options against simiilar things in other board.c files.
4. New architectures must implement all the features all over again, and sometimes in subtley different ways. This places an unfair burden on getting a new architecture fully functional and running with U-Boot.
5. While it is a bit of a tricky change, I believe it is worthwhile and achievable. There is no requirement that all code be common, only that the code that is common should be located in common/board.c rather than arch/xxx/lib/board.c.
All the functions of board_init_f() and board_init_r() are broken into separate function calls so that they can easily be included or excluded for a particular architecture. It also makes it easier to adopt Graeme's initcall proposal later if desired.
Generic relocation is used (see previous series) but now rather than calling relocate_code() to do everything, we call the individual relocation steps one by one. Again this makes it easier to leave things out, particularly for SPL.
ARM is a relatively large board.c file and one which I can test, therefore I think it is a good target for this series. On the other hand, x86 is relatively small and simple, but different enough that it introduces a few issues to be solved. So I have chosen both ARM and x86 for this series.
The next target should probably be PowerPC, since it is large and has some additional features. I suspect we may want to leave some of these very architecture-specific functions in arch/powerpc/lib/board.c, taking out only the generic code. I haven't felt a strong need to do this for ARM/x86, but we could even go as far as putting the initcall list into the architecture-specific board file if the architecture adds a lot of unusual calls.
A generic global_data structure is also required. This might upset a few people. Here is my basic reasoning: most fields are the same, all architectures include and need it, most global_data.h files already have #ifdefs to select fields for a particular SOC, so it is hard to see why architecures are different in this area. We can perhaps add a way to put architecture-specific fields into a separate header file, but for now I have judged that to be counter-productive.
There was dicussion on the list about passing gd_t around as a parameter to pre-relocation init functions. I think this makes sense, but it can be done as a separate change, and this series does not require it.
While this series needs to stand on its own (as with the link script cleanup series and the generic relocation series) the goal is the unification of the board init code. So I hope we can address issues with this in mind, rather than focusing too narrowly on particular ARM or x86 issues.
Comments welcome. Note that the x86 side of this still needs a fair bit of work, sorry.
Simon Glass (19): Introduce generic global_data Make relocation functions global Add basic initcall implementation define CONFIG_SYS_LEGACY_BOARD everywhere Add generic post-relocation board_r.c Add generic pre-relocation board_f.c Add spl load feature switch ARM over to generic board arm: Remove unused code in board.c, global_data.h Add CONFIG_SYS_SYM_OFFSETS to support offset symbols x86: Remove compiler warning in sc520_timer.c x86: Remove dead code in eNET x86: Add processor library and relocation functions Tidy up asm/generic sections.h to include x86 symbols Add fields required by x86 to global_data x86: Change stub example to use asm-generic/sections.h x86: Add initial memory barrier macros Bring in x86 to unified board architecture x86: Remove unused board/global_data code
README | 5 + arch/arm/include/asm/global_data.h | 77 +----- arch/arm/include/asm/u-boot-arm.h | 4 - arch/arm/lib/board.c | 622 +----------------------------------- arch/avr32/config.mk | 3 + arch/blackfin/config.mk | 3 + arch/m68k/config.mk | 3 + arch/microblaze/config.mk | 3 + arch/mips/config.mk | 3 + arch/nds32/config.mk | 3 + arch/nios2/config.mk | 3 + arch/powerpc/config.mk | 3 + arch/sandbox/config.mk | 3 + arch/sh/config.mk | 3 + arch/sparc/config.mk | 3 + arch/x86/config.mk | 3 - arch/x86/cpu/sc520/sc520_timer.c | 2 +- arch/x86/include/asm/global_data.h | 57 +---- arch/x86/include/asm/io.h | 8 + arch/x86/include/asm/reloc.h | 32 ++ arch/x86/include/asm/u-boot-x86.h | 8 - arch/x86/lib/Makefile | 1 + arch/x86/lib/board.c | 452 +-------------------------- arch/x86/lib/proc.S | 67 ++++ board/eNET/eNET.c | 5 - board/freescale/p2020come/Makefile | 6 + common/Makefile | 7 +- common/board_f.c | 461 ++++++++++++++++++++++++++ common/board_r.c | 385 ++++++++++++++++++++++ common/reloc.c | 46 +++- config.mk | 4 + examples/standalone/stubs.c | 7 +- include/asm-generic/global_data.h | 129 ++++++++ include/asm-generic/sections.h | 29 ++ include/initcall.h | 25 ++ include/reloc.h | 16 + lib/Makefile | 1 + lib/initcall.c | 41 +++ 38 files changed, 1308 insertions(+), 1225 deletions(-) create mode 100644 arch/x86/include/asm/reloc.h create mode 100644 arch/x86/lib/proc.S create mode 100644 common/board_f.c create mode 100644 common/board_r.c create mode 100644 include/asm-generic/global_data.h create mode 100644 include/initcall.h create mode 100644 lib/initcall.c

We want to unify the global_data structure. Most fields are common across architectures, but there are a fair number of SOC-specific additions. It isn't clear how best to deal with these, but for now we just use #ifdef.
Checkpatch warnings here might be unavoidable:
warning: include/asm-generic/global_data.h,43: do not add new typedefs warning: include/asm-generic/global_data.h,117: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt warning: include/asm-generic/global_data.h,121: storage class should be at the beginning of the declaration
Signed-off-by: Simon Glass sjg@chromium.org --- include/asm-generic/global_data.h | 125 +++++++++++++++++++++++++++++++++++++ 1 files changed, 125 insertions(+), 0 deletions(-) create mode 100644 include/asm-generic/global_data.h
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h new file mode 100644 index 0000000..16fee5a --- /dev/null +++ b/include/asm-generic/global_data.h @@ -0,0 +1,125 @@ +/* + * (C) Copyright 2002-2010 + * Wolfgang Denk, DENX Software Engineering, wd@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. + * + * 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 + */ + +#ifndef __ASM_GENERIC_GBL_DATA_H +#define __ASM_GENERIC_GBL_DATA_H +/* + * The following data structure is placed in some memory which is + * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or + * some locked parts of the data cache) to allow for a minimum set of + * global variables during system initialization (until we have set + * up the memory controller so that we can use RAM). + * + * Keep it *SMALL* and remember to set GENERATED_GBL_DATA_SIZE > sizeof(gd_t) + * + * sjg@chromium.org: Well it would be nice to have a generic one of these + * since so many fields are similar. But it means that everyone architecture + * will want to add its own nutty fields. Perhaps that is no bad thing since + * it shows up inconsistences and might produce downward pressure on the + * number of fields. + */ + +#ifndef __ASSEMBLY__ +typedef struct global_data { + bd_t *bd; + unsigned long flags; + unsigned long baudrate; + unsigned long have_console; /* serial_init() was called */ +#ifdef CONFIG_PRE_CONSOLE_BUFFER + unsigned long precon_buf_idx; /* Pre-Console buffer index */ +#endif + unsigned long env_addr; /* Address of Environment struct */ + unsigned long env_valid; /* Checksum of Environment valid? */ + unsigned long fb_base; /* base address of frame buffer */ +#ifdef CONFIG_FSL_ESDHC + unsigned long sdhc_clk; +#endif + /* Here begins ARM-specific things. Needs discussion */ +#ifdef CONFIG_AT91FAMILY + /* "static data" needed by at91's clock.c */ + unsigned long cpu_clk_rate_hz; + unsigned long main_clk_rate_hz; + unsigned long mck_rate_hz; + unsigned long plla_rate_hz; + unsigned long pllb_rate_hz; + unsigned long at91_pllb_usb_init; +#endif +#ifdef CONFIG_ARM + /* "static data" needed by most of timer.c on ARM platforms */ + unsigned long timer_rate_hz; + unsigned long tbl; + unsigned long tbu; + unsigned long long timer_reset_value; + unsigned long lastinc; +#endif +#ifdef CONFIG_IXP425 + unsigned long timestamp; +#endif + /* TODO: is this the same as relocaddr, or something else? */ + unsigned long dest_addr; /* Post-relocation address of U-Boot */ + unsigned long dest_addr_sp; + + unsigned long relocaddr; /* Start address of U-Boot in RAM */ + phys_size_t ram_size; /* RAM size */ + unsigned long mon_len; /* monitor len */ + unsigned long irq_sp; /* irq stack pointer */ + unsigned long start_addr_sp; /* start_addr_stackpointer */ + unsigned long reloc_off; +#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) + unsigned long tlb_addr; +#endif + struct global_data *new_gd; /* relocated global data */ + const void *fdt_blob; /* Our device tree, NULL if none */ + void **jt; /* jump table */ + char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) + unsigned long post_log_word; /* Record POST activities */ + unsigned long post_log_res; /* success of POST test */ + unsigned long post_init_f_time; /* When post_init_f started */ +#endif +} gd_t; +#endif + +/* + * Global Data Flags + */ +#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ +#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ +#define GD_FLG_SILENT 0x00004 /* Silent mode */ +#define GD_FLG_POSTFAIL 0x00008 /* Critical POST test failed */ +#define GD_FLG_POSTSTOP 0x00010 /* POST seqeunce aborted */ +#define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ +#define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ +#define GD_FLG_ENV_READY 0x00080 /* Env. imported into hash table */ + +/* ARM uses r8 to hold the global data pointer */ +#ifdef CONFIG_ARM +#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") + +#else /* All other architectures */ + +#define XTRN_DECLARE_GLOBAL_DATA_PTR extern +#define DECLARE_GLOBAL_DATA_PTR XTRN_DECLARE_GLOBAL_DATA_PTR gd_t *gd +#endif + +#endif /* __ASM_GENERIC_GBL_DATA_H */

Dear Simon,
On 28.12.11 07:35, Simon Glass wrote:
We want to unify the global_data structure. Most fields are common across architectures, but there are a fair number of SOC-specific additions. It isn't clear how best to deal with these, but for now we just use #ifdef.
I would like to see some more 'clustering' here. Especially the timer stuff is implementation specific and should therefore not coded directly but with some pointer to the specific stuff i.e. introduce some timer_t which is specific for arm in general and maybe has some more specialization for atmel devices or what else and just save a pointer to that struct in gd_t like it is done with bd_t. Well maybe having a pointer here is stated critical so we could just insert the struct directly and let the compiler decide about the size (BTW this could be done with bd_t now too cause we have a pre-calculated size of gd_t since some time, saves some little steps when instantiating gd_t when running). Beside that we could also introduce some more structs holding specific stuff i.e. console_t, reloc_t, ... (but yes, it should be done in a second step ...)
What do you think about that?
best regards
Andreas Bießmann

Hi Andreas,
On Wed, Dec 28, 2011 at 11:47 PM, Andreas Bießmann andreas.devel@googlemail.com wrote:
Dear Simon,
On 28.12.11 07:35, Simon Glass wrote:
We want to unify the global_data structure. Most fields are common across architectures, but there are a fair number of SOC-specific additions. It isn't clear how best to deal with these, but for now we just use #ifdef.
Sorry your email got a little buried this week.
I would like to see some more 'clustering' here. Especially the timer stuff is implementation specific and should therefore not coded directly but with some pointer to the specific stuff i.e. introduce some timer_t which is specific for arm in general and maybe has some more specialization for atmel devices or what else and just save a pointer to that struct in gd_t like it is done with bd_t.
Actually I wonder if we should an architecture-specific structure, something like
struct global_data { /* generic things first */ ulong baud_rate; ulong ram_size; /* hopefully lots of other things that are mostly common */
/* architecture-specific things */ struct arch_global_data arch; };
struct arch_global_data can be defined in include/asm/global_data.h before it includes include/asm-generic/global_data.h, or the other way around might be better.
One thing I notice is that some architectures share some fields, and others omit them.I feel we should include them at the global level if at least 2 architectures need them. This means that the 'minimal' architectures with hardly any fields will have quite a few unused fields in global_data. I don't think that matters, and the use will increase as that arch gets more functionality.
Well maybe having a pointer here is stated critical so we could just insert the struct directly and let the compiler decide about the size (BTW this could be done with bd_t now too cause we have a pre-calculated size of gd_t since some time, saves some little steps when instantiating gd_t when running).
Yes I agree that just including the structure seems better. A pointer is slower and we just point to a place very close anyway.
It would be nice to subsume bd_t into global_data.
Beside that we could also introduce some more structs holding specific stuff i.e. console_t, reloc_t, ... (but yes, it should be done in a second step ...)
What do you think about that?
Certainly agree for reloc and perhaps there are other cases too. It is far too long at present. Something to think about.
For now I would prefer to do nothing on either point, since bringing everything into one place shows up the conflicts and similarities. Part of the purpose of the generic board effort is to minimise these, and they are hard to spot if they are all in separate files.
But when we get through this, and find that there are things which genuinely are specific to a single arch, then I think breaking them out is reasonable, hopefully combined with joining global_data and bd_t.
Regards, Simon
best regards
Andreas Bießmann

Hi Simon,
On 08/01/12 09:33, Simon Glass wrote:
Hi Andreas,
On Wed, Dec 28, 2011 at 11:47 PM, Andreas Bießmann andreas.devel@googlemail.com wrote:
Dear Simon,
On 28.12.11 07:35, Simon Glass wrote:
We want to unify the global_data structure. Most fields are common across architectures, but there are a fair number of SOC-specific additions. It isn't clear how best to deal with these, but for now we just use #ifdef.
Sorry your email got a little buried this week.
I would like to see some more 'clustering' here. Especially the timer stuff is implementation specific and should therefore not coded directly but with some pointer to the specific stuff i.e. introduce some timer_t which is specific for arm in general and maybe has some more specialization for atmel devices or what else and just save a pointer to that struct in gd_t like it is done with bd_t.
Actually I wonder if we should an architecture-specific structure, something like
struct global_data { /* generic things first */ ulong baud_rate; ulong ram_size; /* hopefully lots of other things that are mostly common */
/* architecture-specific things */ struct arch_global_data arch; };
This makes auto-generated asm offsets a little trickier I think
struct arch_global_data can be defined in include/asm/global_data.h before it includes include/asm-generic/global_data.h, or the other way around might be better.
include/asm-generic/global_data.h would include include/asm/global_data.h
But what of the corner case that an arch has no specific global data?
One thing I notice is that some architectures share some fields, and others omit them.I feel we should include them at the global level if at least 2 architectures need them. This means that the 'minimal' architectures with hardly any fields will have quite a few unused fields in global_data. I don't think that matters, and the use will
I would not bank on that, and I think you will get strong objection from Wolfgang if you try to litter global data with members that are not strictly necessary
increase as that arch gets more functionality.
Well maybe having a pointer here is stated critical so we could just insert the struct directly and let the compiler decide about the size (BTW this could be done with bd_t now too cause we have a pre-calculated size of gd_t since some time, saves some little steps when instantiating gd_t when running).
Yes I agree that just including the structure seems better. A pointer is slower and we just point to a place very close anyway.
Not so fast - The idea is that gd is writeable pre-relocation and therefore can be instantiated in the very limit pre-SDRAM environment such as the CPU cache. bd is not needed until after SDRAM has been initialised, so it's size constraints aren't so bad.
It would be nice to subsume bd_t into global_data.
NAK
Beside that we could also introduce some more structs holding specific stuff i.e. console_t, reloc_t, ... (but yes, it should be done in a second step ...)
What do you think about that?
Certainly agree for reloc and perhaps there are other cases too. It is far too long at present. Something to think about.
I agree that gd could be cleaned up - particularly the types - sub-structuring it is probably a bit over the top though (as I mentioned, how will this impact asm-offsets?
For now I would prefer to do nothing on either point, since bringing everything into one place shows up the conflicts and similarities. Part of the purpose of the generic board effort is to minimise these, and they are hard to spot if they are all in separate files.
Hmm, I'm starting to wonder if we should instead have:
struct gd_generic { /* Relocation stuff */
/* pre-console stuff */
/* Jump table stuff */ }
struct gd { struct gd_generic common;
/* Arch specific stuff */ }
This eliminates the 'no arch specific global data' corner case
But when we get through this, and find that there are things which genuinely are specific to a single arch, then I think breaking them out is reasonable, hopefully combined with joining global_data and bd_t.
Regards,
Graeme

Hi Graeme,
On Sun, Jan 8, 2012 at 2:48 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On 08/01/12 09:33, Simon Glass wrote:
Hi Andreas,
On Wed, Dec 28, 2011 at 11:47 PM, Andreas Bießmann andreas.devel@googlemail.com wrote:
Dear Simon,
On 28.12.11 07:35, Simon Glass wrote:
We want to unify the global_data structure. Most fields are common across architectures, but there are a fair number of SOC-specific additions. It isn't clear how best to deal with these, but for now we just use #ifdef.
Sorry your email got a little buried this week.
I would like to see some more 'clustering' here. Especially the timer stuff is implementation specific and should therefore not coded directly but with some pointer to the specific stuff i.e. introduce some timer_t which is specific for arm in general and maybe has some more specialization for atmel devices or what else and just save a pointer to that struct in gd_t like it is done with bd_t.
Actually I wonder if we should an architecture-specific structure, something like
struct global_data { /* generic things first */ ulong baud_rate; ulong ram_size; /* hopefully lots of other things that are mostly common */
/* architecture-specific things */ struct arch_global_data arch; };
This makes auto-generated asm offsets a little trickier I think
Yes, not impossible though.
struct arch_global_data can be defined in include/asm/global_data.h before it includes include/asm-generic/global_data.h, or the other way around might be better.
include/asm-generic/global_data.h would include include/asm/global_data.h
But what of the corner case that an arch has no specific global data?
Define an empty struct? I would prefer not to do any of this yet anyway, until we know that there are plenty of arch-specific things needed.
One thing I notice is that some architectures share some fields, and others omit them.I feel we should include them at the global level if at least 2 architectures need them. This means that the 'minimal' architectures with hardly any fields will have quite a few unused fields in global_data. I don't think that matters, and the use will
I would not bank on that, and I think you will get strong objection from Wolfgang if you try to litter global data with members that are not strictly necessary
Well we have two solutions: #ifdefs and the arch-specific struct. But the purpose of this series is rather to try to bring everything out so we can see the commonality and check that it is correct before we start changing it further.
increase as that arch gets more functionality.
Well maybe having a pointer here is stated critical so we could just insert the struct directly and let the compiler decide about the size (BTW this could be done with bd_t now too cause we have a pre-calculated size of gd_t since some time, saves some little steps when instantiating gd_t when running).
Yes I agree that just including the structure seems better. A pointer is slower and we just point to a place very close anyway.
Not so fast - The idea is that gd is writeable pre-relocation and therefore can be instantiated in the very limit pre-SDRAM environment such as the CPU cache. bd is not needed until after SDRAM has been initialised, so it's size constraints aren't so bad.
I didn't realise this distinction. Most of the bd_info stuff seems to be things that could just be written into the structure on demand anyway (sort of like a call to arch_get_board_info() or similar) rather than set up at start of day. Perhaps the heavily-used stuff belongs in global_data. Anyway, a discussion for another day.
What is the limit on CPU cache size for SRAM in these architectures? I assume it includes code and data, and is something like 4KB or 8KB at worst?
It would be nice to subsume bd_t into global_data.
NAK
For the above reason? Well for now it is a pointer anyway.
Beside that we could also introduce some more structs holding specific stuff i.e. console_t, reloc_t, ... (but yes, it should be done in a second step ...)
What do you think about that?
Certainly agree for reloc and perhaps there are other cases too. It is far too long at present. Something to think about.
I agree that gd could be cleaned up - particularly the types - sub-structuring it is probably a bit over the top though (as I mentioned, how will this impact asm-offsets?
We can deal with this if we need to, but first we need to see what assembler code actually accesses it. With the effort to move relocation etc. into C from assembler, this may reduce.
For now I would prefer to do nothing on either point, since bringing everything into one place shows up the conflicts and similarities. Part of the purpose of the generic board effort is to minimise these, and they are hard to spot if they are all in separate files.
Hmm, I'm starting to wonder if we should instead have:
struct gd_generic { /* Relocation stuff */
/* pre-console stuff */
/* Jump table stuff */ }
struct gd { struct gd_generic common;
/* Arch specific stuff */ }
This eliminates the 'no arch specific global data' corner case
Maybe. Is it best to #include <asm-generic/global_data.h> instead of <asm/global_data.h> from U-Boot files?
But when we get through this, and find that there are things which genuinely are specific to a single arch, then I think breaking them out is reasonable, hopefully combined with joining global_data and bd_t.
Regards,
Graeme
Regards, Simon

Hi Simon and Graeme,
On 08.01.2012 19:13, Simon Glass wrote:
Hi Graeme,
On Sun, Jan 8, 2012 at 2:48 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On 08/01/12 09:33, Simon Glass wrote:
Hi Andreas,
On Wed, Dec 28, 2011 at 11:47 PM, Andreas Bießmann andreas.devel@googlemail.com wrote:
Dear Simon,
On 28.12.11 07:35, Simon Glass wrote:
<snip discussion about 'how to restructure gd_t' ... should be done later>
For now I would prefer to do nothing on either point, since bringing everything into one place shows up the conflicts and similarities. Part of the purpose of the generic board effort is to minimise these, and they are hard to spot if they are all in separate files.
Currently I agree with you both. It would be best to just move all the specific stuff into one file but let the structure as is (from view of SoC/arch). Later on we could shrink it down by one of the mentioned possibilities.
Hmm, I'm starting to wonder if we should instead have:
struct gd_generic { /* Relocation stuff */
/* pre-console stuff */ /* Jump table stuff */
}
struct gd { struct gd_generic common;
/* Arch specific stuff */
}
This eliminates the 'no arch specific global data' corner case
Sounds good to me, but if we restructure gd_t in any way we should introduce some ability to version the struct for future changes (keep stand alone apps in mind!).
best regards
Andreas Bießmann

Hi Andreas,
On Mon, Jan 9, 2012 at 3:21 AM, Andreas Bießmann andreas.devel@googlemail.com wrote:
Hi Simon and Graeme,
On 08.01.2012 19:13, Simon Glass wrote:
Hi Graeme,
On Sun, Jan 8, 2012 at 2:48 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On 08/01/12 09:33, Simon Glass wrote:
Hi Andreas,
On Wed, Dec 28, 2011 at 11:47 PM, Andreas Bießmann andreas.devel@googlemail.com wrote:
Dear Simon,
On 28.12.11 07:35, Simon Glass wrote:
<snip discussion about 'how to restructure gd_t' ... should be done later>
For now I would prefer to do nothing on either point, since bringing everything into one place shows up the conflicts and similarities. Part of the purpose of the generic board effort is to minimise these, and they are hard to spot if they are all in separate files.
Currently I agree with you both. It would be best to just move all the specific stuff into one file but let the structure as is (from view of SoC/arch). Later on we could shrink it down by one of the mentioned possibilities.
OK good.
Hmm, I'm starting to wonder if we should instead have:
struct gd_generic { /* Relocation stuff */
/* pre-console stuff */
/* Jump table stuff */ }
struct gd { struct gd_generic common;
/* Arch specific stuff */ }
This eliminates the 'no arch specific global data' corner case
Sounds good to me, but if we restructure gd_t in any way we should introduce some ability to version the struct for future changes (keep stand alone apps in mind!).
Yes - in fact just moving to generic board makes the API incompatible. I suspect I should increment something somewhere - will take a look.
Regards, Simon
best regards
Andreas Bießmann

We want to be able to call relocations functions from our new board code, so make them global and add to the header.
Signed-off-by: Simon Glass sjg@chromium.org --- common/reloc.c | 29 ++++++++++++++++++++++++++--- include/reloc.h | 16 ++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/common/reloc.c b/common/reloc.c index 2344e98..ec0d72f 100644 --- a/common/reloc.c +++ b/common/reloc.c @@ -28,7 +28,15 @@
DECLARE_GLOBAL_DATA_PTR;
-static int reloc_make_copy(void) +int reloc_calculate_dest(void) +{ + gd->relocaddr = gd->dest_addr; + gd->reloc_off = gd->dest_addr - CONFIG_SYS_TEXT_BASE; + debug("relocation Offset is: %08lx\n", gd->reloc_off); + return 0; +} + +int reloc_make_copy(void) { char *dst_addr = (char *)gd->relocaddr;
@@ -51,7 +59,7 @@ static int reloc_make_copy(void) return 0; }
-static int reloc_elf(void) +int reloc_elf(void) { #ifndef CONFIG_SPL_BUILD const Elf32_Rel *ptr, *end; @@ -76,7 +84,7 @@ static int reloc_elf(void) return 0; }
-static int reloc_clear_bss(void) +int reloc_clear_bss(void) { char *dst_addr = (char *)_start + _bss_start_ofs; size_t size = _bss_end_ofs - _bss_start_ofs; @@ -93,6 +101,20 @@ static int reloc_clear_bss(void) return 0; }
+#ifndef CONFIG_SYS_LEGACY_BOARD +int reloc_jump_to_copy(void) +{ + /* TODO: tidy this up since we don't want a separate nand_boot() */ +#ifdef CONFIG_NAND_SPL + nand_boot(); +#else + proc_call_board_init_r(gd->new_gd, gd->dest_addr, + (board_init_r_func)board_init_r, + gd->dest_addr_sp); +#endif +} +#endif + void __relocate_code(ulong dest_addr_sp, gd_t *new_gd, ulong dest_addr) { ulong new_board_init_r = (uintptr_t)board_init_r + gd->reloc_off; @@ -106,6 +128,7 @@ void __relocate_code(ulong dest_addr_sp, gd_t *new_gd, ulong dest_addr)
debug("relocation complete: starting from board_init_r() at %lx\n", new_board_init_r); + /* TODO: tidy this up since we don't want a separate nand_boot() */ #ifdef CONFIG_NAND_SPL nand_boot(); diff --git a/include/reloc.h b/include/reloc.h index 79c0a24..adaa3bc 100644 --- a/include/reloc.h +++ b/include/reloc.h @@ -51,4 +51,20 @@ void proc_call_board_init_r(gd_t *new_gd, ulong dest_addr, */ void relocate_code(ulong dest_sp, gd_t *new_gd, ulong dest_addr) __attribute__ ((noreturn)); + +/* Work out the destination code address */ +int reloc_calculate_dest(void); + +/* Make a copy of the U-Boot code in the new location */ +int reloc_make_copy(void); + +/* Fixup relocations in the new code */ +int reloc_elf(void); + +/* Clear the new BSS region */ +int reloc_clear_bss(void); + +/* Jump to the new relocated U-Boot code */ +int reloc_jump_to_copy(void); + #endif

Signed-off-by: Simon Glass sjg@chromium.org --- include/initcall.h | 25 +++++++++++++++++++++++++ lib/Makefile | 1 + lib/initcall.c | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 0 deletions(-) create mode 100644 include/initcall.h create mode 100644 lib/initcall.c
diff --git a/include/initcall.h b/include/initcall.h new file mode 100644 index 0000000..9e54fa5 --- /dev/null +++ b/include/initcall.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * 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. + * + * 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 + */ + +typedef int (*init_fnc_t)(void); + +int initcall_run_list(init_fnc_t init_sequence[]); diff --git a/lib/Makefile b/lib/Makefile index 54708c2..89ddeda 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -40,6 +40,7 @@ COBJS-y += display_options.o COBJS-y += errno.o COBJS-$(CONFIG_OF_CONTROL) += fdtdec.o COBJS-$(CONFIG_GZIP) += gunzip.o +COBJS-y += initcall.o COBJS-y += hashtable.o COBJS-$(CONFIG_LMB) += lmb.o COBJS-y += ldiv.o diff --git a/lib/initcall.c b/lib/initcall.c new file mode 100644 index 0000000..b11048e --- /dev/null +++ b/lib/initcall.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2002-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger mgroeger@sysgo.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. + * + * 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 + */ + +#include <common.h> +#include <initcall.h> + +int initcall_run_list(init_fnc_t init_sequence[]) +{ + init_fnc_t *init_fnc_ptr; + + for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { + if ((*init_fnc_ptr)()) + return -1; + } + return 0; +}

We are introducing a new unified board setup and we want this to be the default. So we need to opt all architectures out first.
Signed-off-by: Simon Glass sjg@chromium.org --- README | 5 +++++ arch/arm/config.mk | 3 +++ arch/avr32/config.mk | 3 +++ arch/blackfin/config.mk | 3 +++ arch/m68k/config.mk | 3 +++ arch/microblaze/config.mk | 3 +++ arch/mips/config.mk | 3 +++ arch/nds32/config.mk | 3 +++ arch/nios2/config.mk | 3 +++ arch/powerpc/config.mk | 3 +++ arch/sandbox/config.mk | 3 +++ arch/sh/config.mk | 3 +++ arch/sparc/config.mk | 3 +++ arch/x86/config.mk | 3 +++ config.mk | 4 ++++ 15 files changed, 48 insertions(+), 0 deletions(-)
diff --git a/README b/README index a076dbf..bf56318 100644 --- a/README +++ b/README @@ -2745,6 +2745,11 @@ Configuration Settings: This makes U-Boot skip relocation for those architectures which don't support it. It is normally defined in arch/xxx/config.mk
+- CONFIG_SYS_LEGACY_BOARD + This selects the legacy architecture-specific board system + instead of the cross-architecture board. It is intended to move + away from this over time. + The following definitions that deal with the placement and management of environment data (variable area); in general, we support the following configurations: diff --git a/arch/arm/config.mk b/arch/arm/config.mk index 45f9dca..31e9ef9 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -33,6 +33,9 @@ endif
PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
+# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y + # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: PF_CPPFLAGS_ARM := $(call cc-option,-marm,)
diff --git a/arch/avr32/config.mk b/arch/avr32/config.mk index 1995983..07d8a6f 100644 --- a/arch/avr32/config.mk +++ b/arch/avr32/config.mk @@ -34,3 +34,6 @@ LDSCRIPT = $(SRCTREE)/$(CPUDIR)/u-boot.lds
# We use legacy relocation for now CONFIG_SYS_SKIP_RELOC := y + +# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y diff --git a/arch/blackfin/config.mk b/arch/blackfin/config.mk index 56047c8..ec7ae4a 100644 --- a/arch/blackfin/config.mk +++ b/arch/blackfin/config.mk @@ -40,6 +40,9 @@ PLATFORM_CPPFLAGS += -DCONFIG_BLACKFIN # Blackfin does not do relocation CONFIG_SYS_SKIP_RELOC := y
+# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y + LDFLAGS_FINAL += --gc-sections LDFLAGS += -m elf32bfin PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections diff --git a/arch/m68k/config.mk b/arch/m68k/config.mk index 52bfc81..b5819f1 100644 --- a/arch/m68k/config.mk +++ b/arch/m68k/config.mk @@ -32,3 +32,6 @@ LDFLAGS_FINAL += --gc-sections
# We use legacy relocation for now CONFIG_SYS_SKIP_RELOC := y + +# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y diff --git a/arch/microblaze/config.mk b/arch/microblaze/config.mk index 7645f2e..148107d 100644 --- a/arch/microblaze/config.mk +++ b/arch/microblaze/config.mk @@ -32,3 +32,6 @@ PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__
# Microblaze does not do relocation CONFIG_SYS_SKIP_RELOC := y + +# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y diff --git a/arch/mips/config.mk b/arch/mips/config.mk index 832b93f..0c7cbd7 100644 --- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -27,6 +27,9 @@ CONFIG_STANDALONE_LOAD_ADDR ?= 0x80200000 -T mips.lds
PLATFORM_CPPFLAGS += -DCONFIG_MIPS -D__MIPS__
+# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y + # # From Linux arch/mips/Makefile # diff --git a/arch/nds32/config.mk b/arch/nds32/config.mk index 4a4499b..0c18d5b 100644 --- a/arch/nds32/config.mk +++ b/arch/nds32/config.mk @@ -36,3 +36,6 @@ LDFLAGS_u-boot = --gc-sections --relax
# We use legacy relocation for now CONFIG_SYS_SKIP_RELOC := y + +# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y diff --git a/arch/nios2/config.mk b/arch/nios2/config.mk index cde7f82..240a4f8 100644 --- a/arch/nios2/config.mk +++ b/arch/nios2/config.mk @@ -34,3 +34,6 @@ PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
# NIOS2 does not do relocation CONFIG_SYS_SKIP_RELOC := y + +# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y diff --git a/arch/powerpc/config.mk b/arch/powerpc/config.mk index eba562f..6a4f59e 100644 --- a/arch/powerpc/config.mk +++ b/arch/powerpc/config.mk @@ -29,6 +29,9 @@ PLATFORM_RELFLAGS += -fpic -mrelocatable -ffunction-sections -fdata-sections PLATFORM_CPPFLAGS += -DCONFIG_PPC -D__powerpc__ PLATFORM_LDFLAGS += -n
+# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y + # # When cross-compiling on NetBSD, we have to define __PPC__ or else we # will pick up a va_list declaration that is incompatible with the diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk index d71326f..a355f84 100644 --- a/arch/sandbox/config.mk +++ b/arch/sandbox/config.mk @@ -22,3 +22,6 @@ PLATFORM_LIBS += -lrt
# Sandbox does not do relocation CONFIG_SYS_SKIP_RELOC := y + +# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y diff --git a/arch/sh/config.mk b/arch/sh/config.mk index 48a7b37..875ad84 100644 --- a/arch/sh/config.mk +++ b/arch/sh/config.mk @@ -34,3 +34,6 @@ LDFLAGS_FINAL = --gc-sections
# SH does not do relocation CONFIG_SYS_SKIP_RELOC := y + +# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y diff --git a/arch/sparc/config.mk b/arch/sparc/config.mk index 032659c..8955ba6 100644 --- a/arch/sparc/config.mk +++ b/arch/sparc/config.mk @@ -29,3 +29,6 @@ PLATFORM_CPPFLAGS += -DCONFIG_SPARC -D__sparc__
# Sparc does not do relocation CONFIG_SYS_SKIP_RELOC := y + +# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 11f3d18..cb8865a 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -51,3 +51,6 @@ export USE_PRIVATE_LIBGCC=$(shell dirname $(PREFIXED_LIBGCC))
# We use legacy relocation for now CONFIG_SYS_SKIP_RELOC := y + +# Move to unified board system later +CONFIG_SYS_LEGACY_BOARD := y diff --git a/config.mk b/config.mk index ddaa477..db5b909 100644 --- a/config.mk +++ b/config.mk @@ -206,6 +206,10 @@ ifeq ($(CONFIG_SPL_BUILD),y) CPPFLAGS += -DCONFIG_SPL_BUILD endif
+ifeq ($(CONFIG_SYS_LEGACY_BOARD),y) +CPPFLAGS += -DCONFIG_SYS_LEGACY_BOARD +endif + ifneq ($(RESET_VECTOR_ADDRESS),) CPPFLAGS += -DRESET_VECTOR_ADDRESS=$(RESET_VECTOR_ADDRESS) endif

This file handles common post-relocation init for boards which use the generic framework.
Signed-off-by: Simon Glass sjg@chromium.org --- board/freescale/p2020come/Makefile | 4 + common/Makefile | 6 +- common/board_r.c | 382 ++++++++++++++++++++++++++++++++++++ 3 files changed, 391 insertions(+), 1 deletions(-) create mode 100644 common/board_r.c
diff --git a/board/freescale/p2020come/Makefile b/board/freescale/p2020come/Makefile index ba87904..d0e1997 100644 --- a/board/freescale/p2020come/Makefile +++ b/board/freescale/p2020come/Makefile @@ -29,6 +29,10 @@ COBJS-y += ddr.o COBJS-y += law.o COBJS-y += tlb.o
+ifndef CONFIG_SYS_LEGACY_BOARD +COBJS += board_r.o +endif + SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(COBJS-y)) SOBJS := $(addprefix $(obj),$(SOBJS)) diff --git a/common/Makefile b/common/Makefile index 3801c28..90601e6 100644 --- a/common/Makefile +++ b/common/Makefile @@ -36,6 +36,11 @@ COBJS-y += s_record.o COBJS-$(CONFIG_SERIAL_MULTI) += serial.o COBJS-y += xyzModem.o
+# boards +ifeq ($(CONFIG_SYS_LEGACY_BOARD),) +COBJS-y += board_r.o +endif + # core command COBJS-y += cmd_boot.o COBJS-$(CONFIG_CMD_BOOTM) += cmd_bootm.o @@ -193,7 +198,6 @@ ifndef CONFIG_SYS_SKIP_RELOC COBJS-y += reloc.o endif
- COBJS := $(sort $(COBJS-y)) XCOBJS := $(sort $(XCOBJS-y)) SRCS := $(COBJS:.o=.c) $(XCOBJS:.o=.c) diff --git a/common/board_r.c b/common/board_r.c new file mode 100644 index 0000000..bd656bd --- /dev/null +++ b/common/board_r.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2002-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger mgroeger@sysgo.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. + * + * 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 + */ + +#include <common.h> +#include <initcall.h> +#include <asm-generic/sections.h> +#include <malloc.h> +#include <mmc.h> +#include <nand.h> +#include <onenand_uboot.h> +#include <serial.h> +#include <stdio_dev.h> + +#ifdef CONFIG_HAS_DATAFLASH +#include <dataflash.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static int initr_reloc(void) +{ + gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ + return 0; +} + +/* + * Some of these functions are needed purely because the functions they + * call return void. If we change them to return 0, these stubs can go away. + */ +static int initr_caches(void) +{ + /* Enable caches */ + enable_caches(); + return 0; +} + +#ifdef CONFIG_SERIAL_MULTI +static int initr_serial(void) +{ + serial_initialize(); + return 0; +} +#endif + +#ifdef CONFIG_LOGBUFFER +static int initr_log(void) +{ + logbuff_init_ptrs(); + return 0; +} +#endif + +#ifdef CONFIG_POST +static int initr_post(void) +{ + post_output_backlog(); + return 0; +} +#endif + +static int initr_malloc(void) +{ + ulong malloc_start; + + /* The malloc area is immediately below the monitor copy in DRAM */ + malloc_start = gd->dest_addr - TOTAL_MALLOC_LEN; + mem_malloc_init(malloc_start, TOTAL_MALLOC_LEN); + return 0; +} + +static int initr_announce(void) +{ + debug("Now running in RAM - U-Boot at: %08lx\n", gd->dest_addr); + return 0; +} + +#if !defined(CONFIG_SYS_NO_FLASH) +static int initr_flash(void) +{ + ulong flash_size; + + puts("Flash: "); + + flash_size = flash_init(); + if (flash_size <= 0) { + puts("*** failed ***\n"); + return -1; + } + print_size(flash_size, ""); +#ifdef CONFIG_SYS_FLASH_CHECKSUM + { + char *s; + + s = getenv("flashchecksum"); + + /* + * Compute and print flash CRC if flashchecksum is set to 'y' + * + * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX + */ + if (s && (*s == 'y')) { + printf(" CRC: %08X", crc32(0, + (const unsigned char *) CONFIG_SYS_FLASH_BASE, + flash_size)); + } + } +#endif /* CONFIG_SYS_FLASH_CHECKSUM */ + putc('\n'); + return 0; +} +#endif + +#ifdef CONFIG_CMD_NAND +/* go init the NAND */ +int initr_nand(void) +{ + puts("NAND: "); + nand_init(); + return 0; +} +#endif + +#if defined(CONFIG_CMD_ONENAND) +/* go init the NAND */ +int initr_onenand(void) +{ + puts("NAND: "); + onenand_init(); + return 0; +} +#endif + +#ifdef CONFIG_GENERIC_MMC +int initr_mmc(void) +{ + puts("MMC: "); + mmc_initialize(gd->bd); + return 0; +} +#endif + +#ifdef CONFIG_HAS_DATAFLASH +/* Ick - why are these not in a header file? */ +extern int AT91F_DataflashInit(void); +extern void dataflash_print_info(void); + +int initr_dataflash(void) +{ + AT91F_DataflashInit(); + dataflash_print_info(); + return 0; +} +#endif + +static int initr_env(void) +{ + /* initialize environment */ + env_relocate(); + + /* IP Address */ + gd->bd->bi_ip_addr = getenv_IPaddr("ipaddr"); + + /* Initialize from environment */ + load_addr = getenv_ulong("loadaddr", 16, load_addr); +#if defined(CONFIG_CMD_NET) + { + char *s = getenv("bootfile"); + + if (s != NULL) + copy_filename(BootFile, s, sizeof(BootFile)); + } +#endif + return 0; +} + +static int initr_jumptable(void) +{ + jumptable_init(); + return 0; +} + +#if defined(CONFIG_API) +static int initr_api(void) +{ + /* Initialize API */ + api_init(); + return 0; +} +#endif + +/* enable exceptions */ +static int initr_enable_interrupts(void) +{ + enable_interrupts(); + return 0; +} + +#if defined(CONFIG_DRIVER_SMC91111) || defined(CONFIG_DRIVER_LAN91C96) +static int initr_ethaddr(void) +{ + /* Perform network card initialisation if necessary */ + /* XXX: this needs to be moved to board init */ + /* YYY: with initcalls the drivers can do this directly */ + /* ZZZ: and anyway why not do it when we call eth_init()? */ + if (getenv("ethaddr")) { + uchar enetaddr[6]; + eth_getenv_enetaddr("ethaddr", enetaddr); + smc_set_mac_addr(enetaddr); + } + return 0; +} +#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */ + +#ifdef CONFIG_BITBANGMII +static init initr_bbmi(void) +{ + bb_miiphy_init(); + return 0; +} +#endif + +#ifdef CONFIG_CMD_NET +static int initr_net(void) +{ + puts("Net: "); + eth_initialize(gd->bd); +#if defined(CONFIG_RESET_PHY_R) + debug("Reset Ethernet PHY\n"); + reset_phy(); +#endif + return 0; +} +#endif + +#ifdef CONFIG_POST +int initr_post(void) +{ + post_run(NULL, POST_RAM | post_bootmode_get(0)); + return 0; +} +#endif + +#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) +/* + * Export available size of memory for Linux, taking into account the + * protected RAM at top of memory + */ +int initr_mem(void) +{ + ulong pram = 0; + uchar memsz[32]; + +# ifdef CONFIG_PRAM + pram = getenv_ulong("pram", 10, CONFIG_PRAM); +# endif +# if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR) + /* Also take the logbuffer into account (pram is in kB) */ + pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024; +# endif + sprintf((char *)memsz, "%ldk", (gd->ram_size / 1024) - pram); + setenv("mem", (char *)memsz); +} +#endif + +static int run_main_loop(void) +{ + /* main_loop() can return to retry autoboot, if so just run it again */ + for (;;) + main_loop(); + return 0; +} + +/* + * Over time we hope to remove these functions with code fragments and + * stub funtcions, and instead call the relevant function directly. + * + * We also hope to remove most of the driver-related init and do it if/when + * the driver is later used. + */ +init_fnc_t init_sequence_r[] = { + initr_reloc, + initr_caches, + /* TODO: could x86 have this also perhaps? */ +#ifdef CONFIG_ARM + board_init, /* Setup chipselects */ +#endif +#ifdef CONFIG_SERIAL_MULTI + initr_serial, +#endif +#ifdef CONFIG_LOGBUFFER + initr_logbuff, +#endif +#ifdef CONFIG_POST + initr_post, +#endif + initr_announce, + initr_malloc, +#ifndef CONFIG_SYS_NO_FLASH + initr_flash, +#endif +#ifdef CONFIG_CMD_NAND + initr_nand, +#endif +#ifdef CONFIG_CMD_ONENAND + initr_onenand, +#endif +#ifdef CONFIG_GENERIC_MMC + initr_mmc, +#endif +#ifdef CONFIG_HAS_DATAFLASH + initr_dataflash, +#endif + initr_env, + stdio_init, + initr_jumptable, +#ifdef CONFIG_API + initr_api, +#endif + console_init_r, /* fully init console as a device */ +#ifdef CONFIG_ARCH_MISC_INIT + arch_misc_init, /* miscellaneous arch-dependent init */ +#endif +#ifdef CONFIG_MISC_INIT_R + misc_init_r, /* miscellaneous platform-dependent init */ +#endif + interrupt_init, + initr_enable_interrupts, + + /* TBD: ick, some of this really shouldn't be here */ +#if defined(CONFIG_DRIVER_SMC91111) || defined(CONFIG_DRIVER_LAN91C96) + initr_ethaddr, +#endif +#ifdef CONFIG_BOARD_LATE_INIT + board_late_init, +#endif +#ifdef CONFIG_BITBANGMII + initr_bbmii, +#endif +#ifdef CONFIG_CMD_NET + initr_net, +#endif +#ifdef CONFIG_POST + initr_post, +#endif + run_main_loop, +}; + +void board_init_r(gd_t *new_gd, ulong dest_addr) +{ + gd = new_gd; + if (initcall_run_list(init_sequence_r)) + hang(); + + /* NOTREACHED - run_main_loop() does not return */ + while (1) + ; +}

This file handles common pre-relocation init for boards which use the generic framework.
It starts up the console, DRAM, performs relocation and then jumps to post-relocation init.
Signed-off-by: Simon Glass sjg@chromium.org --- board/freescale/p2020come/Makefile | 2 + common/Makefile | 1 + common/board_f.c | 430 ++++++++++++++++++++++++++++++++++++ 3 files changed, 433 insertions(+), 0 deletions(-) create mode 100644 common/board_f.c
diff --git a/board/freescale/p2020come/Makefile b/board/freescale/p2020come/Makefile index d0e1997..52538fd 100644 --- a/board/freescale/p2020come/Makefile +++ b/board/freescale/p2020come/Makefile @@ -31,6 +31,8 @@ COBJS-y += tlb.o
ifndef CONFIG_SYS_LEGACY_BOARD COBJS += board_r.o +COBJS += board_f.o +COBJS += reloc.o endif
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) diff --git a/common/Makefile b/common/Makefile index 90601e6..008f131 100644 --- a/common/Makefile +++ b/common/Makefile @@ -38,6 +38,7 @@ COBJS-y += xyzModem.o
# boards ifeq ($(CONFIG_SYS_LEGACY_BOARD),) +COBJS-y += board_f.o COBJS-y += board_r.o endif
diff --git a/common/board_f.c b/common/board_f.c new file mode 100644 index 0000000..f9eb4ca --- /dev/null +++ b/common/board_f.c @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2002-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger mgroeger@sysgo.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. + * + * 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 + */ + +#include <common.h> +#include <version.h> +#include <asm-generic/sections.h> +#include <asm/io.h> +#include <initcall.h> +#include <post.h> +#include <reloc.h> + +#ifdef CONFIG_ARM +/* ARM uses r8 for global data so doesn't need a variable */ +DECLARE_GLOBAL_DATA_PTR; +#else +/* + * Pointer to initial global data area + * + * Here we initialize it. + */ +#undef XTRN_DECLARE_GLOBAL_DATA_PTR +#define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */ +DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR); +#endif + +/* TODO: Move to header file */ +int print_cpuinfo(void); + +/* + * sjg: IMO this code should be + * refactored to a single function, something like: + * + * void led_set_state(enum led_colour_t colour, int on); + */ +/************************************************************************ + * Coloured LED functionality + ************************************************************************ + * May be supplied by boards if desired + */ +inline void __coloured_LED_init(void) {} +void coloured_LED_init(void) + __attribute__((weak, alias("__coloured_LED_init"))); +inline void __red_led_on(void) {} +void red_led_on(void) __attribute__((weak, alias("__red_led_on"))); +inline void __red_led_off(void) {} +void red_led_off(void) __attribute__((weak, alias("__red_led_off"))); +inline void __green_led_on(void) {} +void green_led_on(void) __attribute__((weak, alias("__green_led_on"))); +inline void __green_led_off(void) {} +void green_led_off(void) __attribute__((weak, alias("__green_led_off"))); +inline void __yellow_led_on(void) {} +void yellow_led_on(void) __attribute__((weak, alias("__yellow_led_on"))); +inline void __yellow_led_off(void) {} +void yellow_led_off(void) __attribute__((weak, alias("__yellow_led_off"))); +inline void __blue_led_on(void) {} +void blue_led_on(void) __attribute__((weak, alias("__blue_led_on"))); +inline void __blue_led_off(void) {} +void blue_led_off(void) __attribute__((weak, alias("__blue_led_off"))); + +/* + * Why is gd allocated a register? Prior to reloc it might be better to + * just pass it around to each function in this file? + * + * After reloc one could argue that it is hardly used and doesn't need + * to be in a register. Or if it is it should perhaps hold pointers to all + * global data for all modules, so that post-reloc we can avoid the massive + * literal pool we get on ARM. Or perhaps just encourage each module to use + * a structure... + */ + +/* + * Could the CONFIG_SPL_BUILD infection become a flag in gd? + */ + +static int init_baudrate(void) +{ + gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); + return 0; +} + +static int display_banner(void) +{ + ulong bss_start, bss_end; + + bss_start = _bss_start_ofs + _TEXT_BASE; + bss_end = _bss_end_ofs + _TEXT_BASE; + printf("\n\n%s\n\n", version_string); + debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", + _TEXT_BASE, bss_start, bss_end); + +#ifdef CONFIG_MODEM_SUPPORT + debug("Modem Support enabled\n"); +#endif +#ifdef CONFIG_USE_IRQ + debug("IRQ Stack: %08lx\n", IRQ_STACK_START); + debug("FIQ Stack: %08lx\n", FIQ_STACK_START); +#endif + + return 0; +} + +static int display_dram_config(void) +{ + ulong size = 0; + int i; + + debug("RAM Configuration:\n"); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + size += gd->bd->bi_dram[i].size; + debug("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); +#ifdef DEBUG + print_size(gd->bd->bi_dram[i].size, "\n"); +#endif + } + + puts("DRAM: "); + print_size(size, "\n"); + + return 0; +} + +void __dram_init_banksize(void) +{ +#ifdef CONFIG_SYS_SDRAM_BASE + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_dram[0].size = gd->ram_size; +#endif +} + +void dram_init_banksize(void) + __attribute__((weak, alias("__dram_init_banksize"))); + +static int setup_global_data(void) +{ + /* Pointer is writable since we allocated a register for it */ + gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07); + + /* compiler optimization barrier needed for GCC >= 3.4 */ + dmb(); + memset((void *)gd, '\0', sizeof(gd_t)); + + gd->mon_len = _bss_end_ofs; + return 0; +} + +static int setup_fdt(void) +{ +#ifdef CONFIG_OF_EMBED + /* Get a pointer to the FDT */ + gd->fdt_blob = _binary_dt_dtb_start; +#elif defined CONFIG_OF_SEPARATE + /* FDT is at end of image */ + gd->fdt_blob = (void *)(_end_ofs + CONFIG_SYS_TEXT_BASE); +#endif + /* Allow the early environment to override the fdt address */ + gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, + (uintptr_t)gd->fdt_blob); + return 0; +} + +static int setup_reloc(void) +{ + debug("monitor len: %08lX\n", gd->mon_len); + /* + * Ram is setup, size stored in gd !! + */ + debug("ramsize: %08lX\n", gd->ram_size); +#if defined(CONFIG_SYS_MEM_TOP_HIDE) + /* + * Subtract specified amount of memory to hide so that it won't + * get "touched" at all by U-Boot. By fixing up gd->ram_size + * the Linux kernel should now get passed the now "corrected" + * memory size and won't touch it either. This should work + * for arch/ppc and arch/powerpc. Only Linux board ports in + * arch/powerpc with bootwrapper support, that recalculate the + * memory size from the SDRAM controller setup will have to + * get fixed. + */ + gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE; +#endif + gd->dest_addr = gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; + gd->dest_addr_sp = gd->dest_addr; + return 0; +} + +#if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR) +static int reserve_logbuffer(void) +{ + /* reserve kernel log buffer */ + gd->dest_addr -= LOGBUFF_RESERVE; + debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, + addr); + return 0; +} +#endif + +#ifdef CONFIG_PRAM +/* reserve protected RAM */ +static int reserve_pram(void) +{ + ulong reg; + + reg = getenv_ulong("pram", 10, CONFIG_PRAM); + gd->dest_addr -= (reg << 10); /* size is in kB */ + debug("Reserving %ldk for protected RAM at %08lx\n", reg, + gd->dest_addr); + return 0; +} +#endif /* CONFIG_PRAM */ + +#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) +static int reserve_mmu(void) +{ + /* reserve TLB table */ + gd->dest_addr -= (4096 * 4); + + /* round down to next 64 kB limit */ + gd->dest_addr &= ~(0x10000 - 1); + + gd->tlb_addr = gd->dest_addr; + debug("TLB table at: %08lx\n", gd->tlb_addr); + return 0; +} +#endif + +#ifdef CONFIG_LCD +static int reserve_lcd(void) +{ +#ifdef CONFIG_FB_ADDR + gd->fb_base = CONFIG_FB_ADDR; +#else + /* reserve memory for LCD display (always full pages) */ + gd->dest_addr = lcd_setmem(gd->dest_addr); + gd->fb_base = gd->dest_addr; +#endif /* CONFIG_FB_ADDR */ + return 0; +} +#endif /* CONFIG_LCD */ + +static int reserve_uboot(void) +{ + /* + * reserve memory for U-Boot code, data & bss + * round down to next 4 kB limit + */ + gd->dest_addr -= gd->mon_len; + gd->dest_addr &= ~(4096 - 1); + + debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, + gd->dest_addr); + return 0; +} + +/* reserve memory for malloc() area */ +static int reserve_malloc(void) +{ + gd->dest_addr_sp = gd->dest_addr - TOTAL_MALLOC_LEN; + debug("Reserving %dk for malloc() at: %08lx\n", + TOTAL_MALLOC_LEN >> 10, gd->dest_addr_sp); + return 0; +} + +/* (permanently) allocate a Board Info struct */ +static int reserve_board(void) +{ + gd->dest_addr_sp -= sizeof(bd_t); + gd->bd = (bd_t *)gd->dest_addr_sp; + debug("Reserving %zu Bytes for Board Info at: %08lx\n", + sizeof(bd_t), gd->dest_addr_sp); + return 0; +} + +static int setup_machine(void) +{ +#ifdef CONFIG_MACH_TYPE + gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */ +#endif + return 0; +} + +static int reserve_global_data(void) +{ + gd->dest_addr_sp -= sizeof(gd_t); + gd->new_gd = (gd_t *)gd->dest_addr_sp; + debug("Reserving %zu Bytes for Global Data at: %08lx\n", + sizeof(gd_t), gd->dest_addr_sp); + return 0; +} + +static int reserve_stacks(void) +{ + /* setup stackpointer for exeptions */ + gd->irq_sp = gd->dest_addr_sp; +#ifdef CONFIG_USE_IRQ + gd->dest_addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ); + debug("Reserving %zu Bytes for IRQ stack at: %08lx\n", + CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, gd->dest_addr_sp); +#endif + /* leave 3 words for abort-stack */ + gd->dest_addr_sp -= 12; + + /* 8-byte alignment for ABI compliance */ + gd->dest_addr_sp &= ~0x07; + return 0; +} + +#ifdef CONFIG_POST +static int init_post(void) +{ + post_bootmode_init(); + post_run(NULL, POST_ROM | post_bootmode_get(0)); + return 0; +} +#endif + +static int report_dram_config(void) +{ + /* Ick, can we get rid of this line? */ + gd->bd->bi_baudrate = gd->baudrate; + + /* Ram is board specific, so move it to board code ... */ + dram_init_banksize(); + display_dram_config(); /* and display it */ + return 0; +} + +static init_fnc_t init_sequence_f[] = { + setup_global_data, + setup_fdt, +#if defined(CONFIG_ARCH_CPU_INIT) + arch_cpu_init, /* basic arch cpu dependent setup */ +#endif +#if defined(CONFIG_BOARD_EARLY_INIT_F) + board_early_init_f, +#endif +#ifdef CONFIG_OF_CONTROL + fdtdec_check_fdt, +#endif + timer_init, /* initialize timer */ +#ifdef CONFIG_FSL_ESDHC + get_clocks, +#endif + env_init, /* initialize environment */ + init_baudrate, /* initialze baudrate settings */ + serial_init, /* serial communications setup */ + console_init_f, /* stage 1 init of console */ + display_banner, /* say that we are here */ +#if defined(CONFIG_DISPLAY_CPUINFO) + print_cpuinfo, /* display cpu info (and speed) */ +#endif +#if defined(CONFIG_DISPLAY_BOARDINFO) + checkboard, /* display board info */ +#endif + dram_init, /* configure available RAM banks */ + setup_reloc, +#if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR) + reserve_logbuffer, +#endif +#ifdef CONFIG_PRAM + reserve_pram, +#endif +#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) + reserve_mmu, +#endif +#ifdef CONFIG_LCD + reserve_lcd, +#endif + reserve_uboot, + reserve_malloc, + reserve_board, + setup_machine, + reserve_global_data, + reserve_stacks, +#ifdef CONFIG_POST + init_post, +#endif + report_dram_config, + reloc_calculate_dest, + reloc_make_copy, + reloc_elf, + reloc_clear_bss, + reloc_jump_to_copy, + NULL, +}; + +void board_init_f(ulong bootflags) +{ + /* TODO: perhaps declare gd as a local variable */ + + /* TODO: save bootflag into gd->flags */ + if (initcall_run_list(init_sequence_f)) + hang(); + + /* NOTREACHED - jump_to_copy() does not return */ + while (1) + ; +} + +void hang(void) +{ + puts("### ERROR ### Please RESET the board ###\n"); + for (;;) + ; +}

Signed-off-by: Simon Glass sjg@chromium.org --- common/board_f.c | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c index f9eb4ca..06317ed 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -277,6 +277,7 @@ static int reserve_uboot(void) return 0; }
+#ifndef CONFIG_SPL_BUILD /* reserve memory for malloc() area */ static int reserve_malloc(void) { @@ -295,6 +296,7 @@ static int reserve_board(void) sizeof(bd_t), gd->dest_addr_sp); return 0; } +#endif
static int setup_machine(void) { @@ -313,6 +315,7 @@ static int reserve_global_data(void) return 0; }
+#ifndef CONFIG_SPL_BUILD static int reserve_stacks(void) { /* setup stackpointer for exeptions */ @@ -329,6 +332,17 @@ static int reserve_stacks(void) gd->dest_addr_sp &= ~0x07; return 0; } +#endif + +#ifdef CONFIG_SPL_BUILD +static int reserve_stacks_spl(void) +{ + /* Why not -= ? */ + gd->dest_addr_sp += 128; /* leave 32 words for abort-stack */ + gd->irq_sp = gd->dest_addr_sp; + return 0; +} +#endif
#ifdef CONFIG_POST static int init_post(void) @@ -392,18 +406,26 @@ static init_fnc_t init_sequence_f[] = { reserve_lcd, #endif reserve_uboot, +#ifndef CONFIG_SPL_BUILD reserve_malloc, reserve_board, +#endif setup_machine, reserve_global_data, +#ifdef CONFIG_SPL_BUILD + reserve_stacks_spl, +#else reserve_stacks, +#endif #ifdef CONFIG_POST init_post, #endif report_dram_config, reloc_calculate_dest, reloc_make_copy, +#ifndef CONFIG_SPL_BUILD reloc_elf, +#endif reloc_clear_bss, reloc_jump_to_copy, NULL,

Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/config.mk | 3 --- arch/arm/include/asm/global_data.h | 8 ++++++++ arch/arm/lib/Makefile | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/arm/config.mk b/arch/arm/config.mk index 31e9ef9..45f9dca 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -33,9 +33,6 @@ endif
PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
-# Move to unified board system later -CONFIG_SYS_LEGACY_BOARD := y - # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: PF_CPPFLAGS_ARM := $(call cc-option,-marm,)
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index c3ff789..e31e06a 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -23,6 +23,13 @@
#ifndef __ASM_GBL_DATA_H #define __ASM_GBL_DATA_H + +#ifndef CONFIG_SYS_LEGACY_BOARD + +/* Use the generic board which requires a unified global_data */ +#include <asm-generic/global_data.h> + +#else /* * The following data structure is placed in some memory which is * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or @@ -99,5 +106,6 @@ typedef struct global_data { #define GD_FLG_ENV_READY 0x00080 /* Environment imported into hash table */
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") +#endif /* CONFIG_SYS_LEGACY_BOARD */
#endif /* __ASM_GBL_DATA_H */ diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 213c76f..fd3b331 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -37,7 +37,9 @@ GLSOBJS += _umodsi3.o
GLCOBJS += div0.o
+ifeq ($(CONFIG_SYS_LEGACY_BOARD),y) COBJS-y += board.o +endif COBJS-y += bootm.o COBJS-y += cache.o COBJS-y += cache-cp15.o

Now that ARM uses the generic board, we don't need this code.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/include/asm/global_data.h | 81 ----- arch/arm/lib/Makefile | 2 - arch/arm/lib/board.c | 622 +----------------------------------- 3 files changed, 9 insertions(+), 696 deletions(-)
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index e31e06a..0251aad 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -24,88 +24,7 @@ #ifndef __ASM_GBL_DATA_H #define __ASM_GBL_DATA_H
-#ifndef CONFIG_SYS_LEGACY_BOARD - /* Use the generic board which requires a unified global_data */ #include <asm-generic/global_data.h>
-#else -/* - * The following data structure is placed in some memory which is - * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or - * some locked parts of the data cache) to allow for a minimum set of - * global variables during system initialization (until we have set - * up the memory controller so that we can use RAM). - * - * Keep it *SMALL* and remember to set GENERATED_GBL_DATA_SIZE > sizeof(gd_t) - */ - -typedef struct global_data { - bd_t *bd; - unsigned long flags; - unsigned long baudrate; - unsigned long have_console; /* serial_init() was called */ -#ifdef CONFIG_PRE_CONSOLE_BUFFER - unsigned long precon_buf_idx; /* Pre-Console buffer index */ -#endif - unsigned long env_addr; /* Address of Environment struct */ - unsigned long env_valid; /* Checksum of Environment valid? */ - unsigned long fb_base; /* base address of frame buffer */ -#ifdef CONFIG_FSL_ESDHC - unsigned long sdhc_clk; -#endif -#ifdef CONFIG_AT91FAMILY - /* "static data" needed by at91's clock.c */ - unsigned long cpu_clk_rate_hz; - unsigned long main_clk_rate_hz; - unsigned long mck_rate_hz; - unsigned long plla_rate_hz; - unsigned long pllb_rate_hz; - unsigned long at91_pllb_usb_init; -#endif -#ifdef CONFIG_ARM - /* "static data" needed by most of timer.c on ARM platforms */ - unsigned long timer_rate_hz; - unsigned long tbl; - unsigned long tbu; - unsigned long long timer_reset_value; - unsigned long lastinc; -#endif -#ifdef CONFIG_IXP425 - unsigned long timestamp; -#endif - unsigned long relocaddr; /* Start address of U-Boot in RAM */ - phys_size_t ram_size; /* RAM size */ - unsigned long mon_len; /* monitor len */ - unsigned long irq_sp; /* irq stack pointer */ - unsigned long start_addr_sp; /* start_addr_stackpointer */ - unsigned long reloc_off; -#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) - unsigned long tlb_addr; -#endif - const void *fdt_blob; /* Our device tree, NULL if none */ - void **jt; /* jump table */ - char env_buf[32]; /* buffer for getenv() before reloc. */ -#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) - unsigned long post_log_word; /* Record POST activities */ - unsigned long post_log_res; /* success of POST test */ - unsigned long post_init_f_time; /* When post_init_f started */ -#endif -} gd_t; - -/* - * Global Data Flags - */ -#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ -#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ -#define GD_FLG_SILENT 0x00004 /* Silent mode */ -#define GD_FLG_POSTFAIL 0x00008 /* Critical POST test failed */ -#define GD_FLG_POSTSTOP 0x00010 /* POST seqeunce aborted */ -#define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ -#define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ -#define GD_FLG_ENV_READY 0x00080 /* Environment imported into hash table */ - -#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") -#endif /* CONFIG_SYS_LEGACY_BOARD */ - #endif /* __ASM_GBL_DATA_H */ diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index fd3b331..213c76f 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -37,9 +37,7 @@ GLSOBJS += _umodsi3.o
GLCOBJS += div0.o
-ifeq ($(CONFIG_SYS_LEGACY_BOARD),y) COBJS-y += board.o -endif COBJS-y += bootm.o COBJS-y += cache.o COBJS-y += cache-cp15.o diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index bf1bf79..71018e0 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -1,4 +1,6 @@ /* + * Copyright (c) 2011 The Chromium OS Authors. + * * (C) Copyright 2002-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * @@ -26,619 +28,13 @@ */
/* - * To match the U-Boot user interface on ARM platforms to the U-Boot - * standard (as on PPC platforms), some messages with debug character - * are removed from the default U-Boot build. + * This file is currently unused, since ARM now uses the generic board + * implementation in common/board_f.c and common/board_r.c. If you are + * missing something, take a look there instead. * - * Define DEBUG here if you want additional info as shown below - * printed upon startup: + * You may in principle add functions here that are truly ARM-specific. + * This file could also be used to hold the initcall arrays, if it turns + * out that the differences for ARM are large enough to justify it. * - * U-Boot code: 00F00000 -> 00F3C774 BSS: -> 00FC3274 - * IRQ Stack: 00ebff7c - * FIQ Stack: 00ebef7c - */ - -#include <common.h> -#include <command.h> -#include <malloc.h> -#include <reloc.h> -#include <stdio_dev.h> -#include <version.h> -#include <net.h> -#include <serial.h> -#include <nand.h> -#include <onenand_uboot.h> -#include <mmc.h> -#include <libfdt.h> -#include <fdtdec.h> -#include <post.h> -#include <logbuff.h> - -#ifdef CONFIG_BITBANGMII -#include <miiphy.h> -#endif - -#ifdef CONFIG_DRIVER_SMC91111 -#include "../drivers/net/smc91111.h" -#endif -#ifdef CONFIG_DRIVER_LAN91C96 -#include "../drivers/net/lan91c96.h" -#endif - -DECLARE_GLOBAL_DATA_PTR; - -ulong monitor_flash_len; - -#ifdef CONFIG_HAS_DATAFLASH -extern int AT91F_DataflashInit(void); -extern void dataflash_print_info(void); -#endif - -#if defined(CONFIG_HARD_I2C) || \ - defined(CONFIG_SOFT_I2C) -#include <i2c.h> -#endif - -/************************************************************************ - * Coloured LED functionality - ************************************************************************ - * May be supplied by boards if desired - */ -inline void __coloured_LED_init(void) {} -void coloured_LED_init(void) - __attribute__((weak, alias("__coloured_LED_init"))); -inline void __red_led_on(void) {} -void red_led_on(void) __attribute__((weak, alias("__red_led_on"))); -inline void __red_led_off(void) {} -void red_led_off(void) __attribute__((weak, alias("__red_led_off"))); -inline void __green_led_on(void) {} -void green_led_on(void) __attribute__((weak, alias("__green_led_on"))); -inline void __green_led_off(void) {} -void green_led_off(void) __attribute__((weak, alias("__green_led_off"))); -inline void __yellow_led_on(void) {} -void yellow_led_on(void) __attribute__((weak, alias("__yellow_led_on"))); -inline void __yellow_led_off(void) {} -void yellow_led_off(void) __attribute__((weak, alias("__yellow_led_off"))); -inline void __blue_led_on(void) {} -void blue_led_on(void) __attribute__((weak, alias("__blue_led_on"))); -inline void __blue_led_off(void) {} -void blue_led_off(void) __attribute__((weak, alias("__blue_led_off"))); - -/* - ************************************************************************ - * Init Utilities * - ************************************************************************ - * Some of this code should be moved into the core functions, - * or dropped completely, - * but let's get it working (again) first... - */ - -#if defined(CONFIG_ARM_DCC) && !defined(CONFIG_BAUDRATE) -#define CONFIG_BAUDRATE 115200 -#endif - -static int init_baudrate(void) -{ - gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); - return 0; -} - -static int display_banner(void) -{ - printf("\n\n%s\n\n", version_string); - debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", - _TEXT_BASE, - _bss_start_ofs + _TEXT_BASE, _bss_end_ofs + _TEXT_BASE); -#ifdef CONFIG_MODEM_SUPPORT - debug("Modem Support enabled\n"); -#endif -#ifdef CONFIG_USE_IRQ - debug("IRQ Stack: %08lx\n", IRQ_STACK_START); - debug("FIQ Stack: %08lx\n", FIQ_STACK_START); -#endif - - return (0); -} - -/* - * WARNING: this code looks "cleaner" than the PowerPC version, but - * has the disadvantage that you either get nothing, or everything. - * On PowerPC, you might see "DRAM: " before the system hangs - which - * gives a simple yet clear indication which part of the - * initialization if failing. + * Hopefully not, in which case perhaps we will remove this file. */ -static int display_dram_config(void) -{ - int i; - -#ifdef DEBUG - puts("RAM Configuration:\n"); - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - printf("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); - print_size(gd->bd->bi_dram[i].size, "\n"); - } -#else - ulong size = 0; - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) - size += gd->bd->bi_dram[i].size; - - puts("DRAM: "); - print_size(size, "\n"); -#endif - - return (0); -} - -#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) -static int init_func_i2c(void) -{ - puts("I2C: "); - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - puts("ready\n"); - return (0); -} -#endif - -#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI) -#include <pci.h> -static int arm_pci_init(void) -{ - pci_init(); - return 0; -} -#endif /* CONFIG_CMD_PCI || CONFIG_PCI */ - -/* - * Breathe some life into the board... - * - * Initialize a serial port as console, and carry out some hardware - * tests. - * - * The first part of initialization is running from Flash memory; - * its main purpose is to initialize the RAM so that we - * can relocate the monitor code to RAM. - */ - -/* - * All attempts to come up with a "common" initialization sequence - * that works for all boards and architectures failed: some of the - * requirements are just _too_ different. To get rid of the resulting - * mess of board dependent #ifdef'ed code we now make the whole - * initialization sequence configurable to the user. - * - * The requirements for any new initalization function is simple: it - * receives a pointer to the "global data" structure as it's only - * argument, and returns an integer return code, where 0 means - * "continue" and != 0 means "fatal error, hang the system". - */ -typedef int (init_fnc_t) (void); - -int print_cpuinfo(void); - -void __dram_init_banksize(void) -{ - gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; - gd->bd->bi_dram[0].size = gd->ram_size; -} -void dram_init_banksize(void) - __attribute__((weak, alias("__dram_init_banksize"))); - -init_fnc_t *init_sequence[] = { -#if defined(CONFIG_ARCH_CPU_INIT) - arch_cpu_init, /* basic arch cpu dependent setup */ -#endif -#if defined(CONFIG_BOARD_EARLY_INIT_F) - board_early_init_f, -#endif -#ifdef CONFIG_OF_CONTROL - fdtdec_check_fdt, -#endif - timer_init, /* initialize timer */ -#ifdef CONFIG_FSL_ESDHC - get_clocks, -#endif - env_init, /* initialize environment */ - init_baudrate, /* initialze baudrate settings */ - serial_init, /* serial communications setup */ - console_init_f, /* stage 1 init of console */ - display_banner, /* say that we are here */ -#if defined(CONFIG_DISPLAY_CPUINFO) - print_cpuinfo, /* display cpu info (and speed) */ -#endif -#if defined(CONFIG_DISPLAY_BOARDINFO) - checkboard, /* display board info */ -#endif -#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) - init_func_i2c, -#endif - dram_init, /* configure available RAM banks */ - NULL, -}; - -void board_init_f(ulong bootflag) -{ - bd_t *bd; - init_fnc_t **init_fnc_ptr; - gd_t *id; - ulong addr, addr_sp; -#ifdef CONFIG_PRAM - ulong reg; -#endif - - /* Pointer is writable since we allocated a register for it */ - gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07); - /* compiler optimization barrier needed for GCC >= 3.4 */ - __asm__ __volatile__("": : :"memory"); - - memset((void *)gd, 0, sizeof(gd_t)); - - gd->mon_len = _bss_end_ofs; -#ifdef CONFIG_OF_EMBED - /* Get a pointer to the FDT */ - gd->fdt_blob = _binary_dt_dtb_start; -#elif defined CONFIG_OF_SEPARATE - /* FDT is at end of image */ - gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE); -#endif - /* Allow the early environment to override the fdt address */ - gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, - (uintptr_t)gd->fdt_blob); - - for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { - if ((*init_fnc_ptr)() != 0) { - hang (); - } - } - - debug("monitor len: %08lX\n", gd->mon_len); - /* - * Ram is setup, size stored in gd !! - */ - debug("ramsize: %08lX\n", gd->ram_size); -#if defined(CONFIG_SYS_MEM_TOP_HIDE) - /* - * Subtract specified amount of memory to hide so that it won't - * get "touched" at all by U-Boot. By fixing up gd->ram_size - * the Linux kernel should now get passed the now "corrected" - * memory size and won't touch it either. This should work - * for arch/ppc and arch/powerpc. Only Linux board ports in - * arch/powerpc with bootwrapper support, that recalculate the - * memory size from the SDRAM controller setup will have to - * get fixed. - */ - gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE; -#endif - - addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; - -#ifdef CONFIG_LOGBUFFER -#ifndef CONFIG_ALT_LB_ADDR - /* reserve kernel log buffer */ - addr -= (LOGBUFF_RESERVE); - debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, - addr); -#endif -#endif - -#ifdef CONFIG_PRAM - /* - * reserve protected RAM - */ - reg = getenv_ulong("pram", 10, CONFIG_PRAM); - addr -= (reg << 10); /* size is in kB */ - debug("Reserving %ldk for protected RAM at %08lx\n", reg, addr); -#endif /* CONFIG_PRAM */ - -#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) - /* reserve TLB table */ - addr -= (4096 * 4); - - /* round down to next 64 kB limit */ - addr &= ~(0x10000 - 1); - - gd->tlb_addr = addr; - debug("TLB table at: %08lx\n", addr); -#endif - - /* round down to next 4 kB limit */ - addr &= ~(4096 - 1); - debug("Top of RAM usable for U-Boot at: %08lx\n", addr); - -#ifdef CONFIG_LCD -#ifdef CONFIG_FB_ADDR - gd->fb_base = CONFIG_FB_ADDR; -#else - /* reserve memory for LCD display (always full pages) */ - addr = lcd_setmem(addr); - gd->fb_base = addr; -#endif /* CONFIG_FB_ADDR */ -#endif /* CONFIG_LCD */ - - /* - * reserve memory for U-Boot code, data & bss - * round down to next 4 kB limit - */ - addr -= gd->mon_len; - addr &= ~(4096 - 1); - - debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr); - -#ifndef CONFIG_SPL_BUILD - /* - * reserve memory for malloc() arena - */ - addr_sp = addr - TOTAL_MALLOC_LEN; - debug("Reserving %dk for malloc() at: %08lx\n", - TOTAL_MALLOC_LEN >> 10, addr_sp); - /* - * (permanently) allocate a Board Info struct - * and a permanent copy of the "global" data - */ - addr_sp -= sizeof (bd_t); - bd = (bd_t *) addr_sp; - gd->bd = bd; - debug("Reserving %zu Bytes for Board Info at: %08lx\n", - sizeof (bd_t), addr_sp); - -#ifdef CONFIG_MACH_TYPE - gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */ -#endif - - addr_sp -= sizeof (gd_t); - id = (gd_t *) addr_sp; - debug("Reserving %zu Bytes for Global Data at: %08lx\n", - sizeof (gd_t), addr_sp); - - /* setup stackpointer for exeptions */ - gd->irq_sp = addr_sp; -#ifdef CONFIG_USE_IRQ - addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ); - debug("Reserving %zu Bytes for IRQ stack at: %08lx\n", - CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp); -#endif - /* leave 3 words for abort-stack */ - addr_sp -= 12; - - /* 8-byte alignment for ABI compliance */ - addr_sp &= ~0x07; -#else - addr_sp += 128; /* leave 32 words for abort-stack */ - gd->irq_sp = addr_sp; -#endif - - debug("New Stack Pointer is: %08lx\n", addr_sp); - -#ifdef CONFIG_POST - post_bootmode_init(); - post_run(NULL, POST_ROM | post_bootmode_get(0)); -#endif - - gd->bd->bi_baudrate = gd->baudrate; - /* Ram ist board specific, so move it to board code ... */ - dram_init_banksize(); - display_dram_config(); /* and display it */ - - gd->relocaddr = addr; - gd->start_addr_sp = addr_sp; - gd->reloc_off = addr - _TEXT_BASE; - debug("relocation Offset is: %08lx\n", gd->reloc_off); - memcpy(id, (void *)gd, sizeof(gd_t)); - - relocate_code(addr_sp, id, addr); - - /* NOTREACHED - relocate_code() does not return */ -} - -#if !defined(CONFIG_SYS_NO_FLASH) -static char *failed = "*** failed ***\n"; -#endif - -/* - ************************************************************************ - * - * This is the next part if the initialization sequence: we are now - * running from RAM and have a "normal" C environment, i. e. global - * data can be written, BSS has been cleared, the stack size in not - * that critical any more, etc. - * - ************************************************************************ - */ - -void board_init_r(gd_t *id, ulong dest_addr) -{ - ulong malloc_start; -#if !defined(CONFIG_SYS_NO_FLASH) - ulong flash_size; -#endif - - gd = id; - - gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ - - monitor_flash_len = _end_ofs; - - /* Enable caches */ - enable_caches(); - - debug("monitor flash len: %08lX\n", monitor_flash_len); - board_init(); /* Setup chipselects */ - -#ifdef CONFIG_SERIAL_MULTI - serial_initialize(); -#endif - - debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr); - -#ifdef CONFIG_LOGBUFFER - logbuff_init_ptrs(); -#endif -#ifdef CONFIG_POST - post_output_backlog(); -#endif - - /* The Malloc area is immediately below the monitor copy in DRAM */ - malloc_start = dest_addr - TOTAL_MALLOC_LEN; - mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN); - -#if !defined(CONFIG_SYS_NO_FLASH) - puts("Flash: "); - - flash_size = flash_init(); - if (flash_size > 0) { -# ifdef CONFIG_SYS_FLASH_CHECKSUM - char *s = getenv("flashchecksum"); - - print_size(flash_size, ""); - /* - * Compute and print flash CRC if flashchecksum is set to 'y' - * - * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX - */ - if (s && (*s == 'y')) { - printf(" CRC: %08X", crc32(0, - (const unsigned char *) CONFIG_SYS_FLASH_BASE, - flash_size)); - } - putc('\n'); -# else /* !CONFIG_SYS_FLASH_CHECKSUM */ - print_size(flash_size, "\n"); -# endif /* CONFIG_SYS_FLASH_CHECKSUM */ - } else { - puts(failed); - hang(); - } -#endif - -#if defined(CONFIG_CMD_NAND) - puts("NAND: "); - nand_init(); /* go init the NAND */ -#endif - -#if defined(CONFIG_CMD_ONENAND) - onenand_init(); -#endif - -#ifdef CONFIG_GENERIC_MMC - puts("MMC: "); - mmc_initialize(gd->bd); -#endif - -#ifdef CONFIG_HAS_DATAFLASH - AT91F_DataflashInit(); - dataflash_print_info(); -#endif - - /* initialize environment */ - env_relocate(); - -#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI) - arm_pci_init(); -#endif - - /* IP Address */ - gd->bd->bi_ip_addr = getenv_IPaddr("ipaddr"); - - stdio_init(); /* get the devices list going. */ - - jumptable_init(); - -#if defined(CONFIG_API) - /* Initialize API */ - api_init(); -#endif - - console_init_r(); /* fully init console as a device */ - -#if defined(CONFIG_ARCH_MISC_INIT) - /* miscellaneous arch dependent initialisations */ - arch_misc_init(); -#endif -#if defined(CONFIG_MISC_INIT_R) - /* miscellaneous platform dependent initialisations */ - misc_init_r(); -#endif - - /* set up exceptions */ - interrupt_init(); - /* enable exceptions */ - enable_interrupts(); - - /* Perform network card initialisation if necessary */ -#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96) - /* XXX: this needs to be moved to board init */ - if (getenv("ethaddr")) { - uchar enetaddr[6]; - eth_getenv_enetaddr("ethaddr", enetaddr); - smc_set_mac_addr(enetaddr); - } -#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */ - - /* Initialize from environment */ - load_addr = getenv_ulong("loadaddr", 16, load_addr); -#if defined(CONFIG_CMD_NET) - { - char *s = getenv("bootfile"); - - if (s != NULL) - copy_filename(BootFile, s, sizeof(BootFile)); - } -#endif - -#ifdef CONFIG_BOARD_LATE_INIT - board_late_init(); -#endif - -#ifdef CONFIG_BITBANGMII - bb_miiphy_init(); -#endif -#if defined(CONFIG_CMD_NET) - puts("Net: "); - eth_initialize(gd->bd); -#if defined(CONFIG_RESET_PHY_R) - debug("Reset Ethernet PHY\n"); - reset_phy(); -#endif -#endif - -#ifdef CONFIG_POST - post_run(NULL, POST_RAM | post_bootmode_get(0)); -#endif - -#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) - /* - * Export available size of memory for Linux, - * taking into account the protected RAM at top of memory - */ - { - ulong pram = 0; - uchar memsz[32]; - -#ifdef CONFIG_PRAM - pram = getenv_ulong("pram", 10, CONFIG_PRAM); -#endif -#ifdef CONFIG_LOGBUFFER -#ifndef CONFIG_ALT_LB_ADDR - /* Also take the logbuffer into account (pram is in kB) */ - pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024; -#endif -#endif - sprintf((char *)memsz, "%ldk", (gd->ram_size / 1024) - pram); - setenv("mem", (char *)memsz); - } -#endif - - /* main_loop() can return to retry autoboot, if so just run it again. */ - for (;;) { - main_loop(); - } - - /* NOTREACHED - no way out of command loop except booting */ -} - -void hang(void) -{ - puts("### ERROR ### Please RESET the board ###\n"); - for (;;); -}

Link symbols as created by the link script can either be absolute or relative to the text start. This option switches between the two options so that we can support both.
As we convert architectures over to generic board, we can see if this option is actually needed, or whether it is possible to unify this feature also.
Signed-off-by: Simon Glass sjg@chromium.org --- common/board_f.c | 9 +++++++++ common/reloc.c | 17 ++++++++++++++++- include/asm-generic/sections.h | 11 +++++++++++ 3 files changed, 36 insertions(+), 1 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c index 06317ed..17fcf08 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -107,8 +107,13 @@ static int display_banner(void) { ulong bss_start, bss_end;
+#ifdef CONFIG_SYS_SYM_OFFSETS bss_start = _bss_start_ofs + _TEXT_BASE; bss_end = _bss_end_ofs + _TEXT_BASE; +#else + bss_start = (ulong)&__bss_start; + bss_end = (ulong)&__bss_end; +#endif printf("\n\n%s\n\n", version_string); debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", _TEXT_BASE, bss_start, bss_end); @@ -165,7 +170,11 @@ static int setup_global_data(void) dmb(); memset((void *)gd, '\0', sizeof(gd_t));
+#ifdef CONFIG_SYS_SYM_OFFSETS gd->mon_len = _bss_end_ofs; +#else + gd->mon_len = (ulong)&__bss_end - (ulong)&__text_start; +#endif return 0; }
diff --git a/common/reloc.c b/common/reloc.c index ec0d72f..564cc67 100644 --- a/common/reloc.c +++ b/common/reloc.c @@ -43,11 +43,15 @@ int reloc_make_copy(void) /* TODO: __text_start would be better when we have it */ char *src_addr = (char *)_start; /* TODO: switch over to __image_copy_end when we can */ +#ifdef CONFIG_SYS_SYM_OFFSETS #ifdef CONFIG_SPL_BUILD char *end_addr = src_addr + _image_copy_end_ofs; #else char *end_addr = src_addr + _rel_dyn_start_ofs; #endif +#else + char *end_addr = (char *)&__data_end; +#endif
if (dst_addr != src_addr) { size_t size = end_addr - src_addr; @@ -64,14 +68,20 @@ int reloc_elf(void) #ifndef CONFIG_SPL_BUILD const Elf32_Rel *ptr, *end; Elf32_Addr *addr; - char *src_addr = (char *)_start; Elf32_Sym *dynsym; ulong reloc_ofs = gd->reloc_off;
/* scan the relocation table for relevant entries */ +#ifdef CONFIG_SYS_SYM_OFFSETS + char *src_addr = (char *)_start; + ptr = (Elf32_Rel *)(src_addr + _rel_dyn_start_ofs); end = (Elf32_Rel *)(src_addr + _rel_dyn_end_ofs); dynsym = (Elf32_Sym *)(src_addr + _dynsym_start_ofs); +#else + ptr = (Elf32_Rel *)(&__rel_dyn_start); + end = (Elf32_Rel *)(&__rel_dyn_end); +#endif debug("%s: process reloc entries %p-%p, dynsym at %p\n", __func__, ptr, end, dynsym); for (; ptr < end; ptr++) { @@ -86,8 +96,13 @@ int reloc_elf(void)
int reloc_clear_bss(void) { +#ifdef CONFIG_SYS_SYM_OFFSETS char *dst_addr = (char *)_start + _bss_start_ofs; size_t size = _bss_end_ofs - _bss_start_ofs; +#else + ulong *dst_addr = (ulong *)((ulong)&__bss_start + gd->reloc_off); + size_t size = (size_t)&__bss_end - (size_t)&__bss_start; +#endif
#ifndef CONFIG_SPL_BUILD /* No relocation for SPL (TBD: better to set reloc_off to zero) */ diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 2935dc1..0dac424 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -79,6 +79,17 @@ extern char __image_copy_end[]; */ extern void _start(void);
+/* + * ARM needs to use offsets for symbols, since the values of some symbols + * are not resolved prior to relocation (and are just 0). Maybe this can be + * resolved, or maybe other architectures are similar, iwc this should be + * promoted to an architecture option. + */ +#ifdef CONFIG_ARM +#define CONFIG_SYS_SYM_OFFSETS +#endif + +#ifdef CONFIG_SYS_SYM_OFFSETS /* Start/end of the relocation entries, as an offset from _start */ extern ulong _rel_dyn_start_ofs; extern ulong _rel_dyn_end_ofs;

Removes 'set but not used' warning.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/cpu/sc520/sc520_timer.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/x86/cpu/sc520/sc520_timer.c b/arch/x86/cpu/sc520/sc520_timer.c index 495a694..7f812dc 100644 --- a/arch/x86/cpu/sc520/sc520_timer.c +++ b/arch/x86/cpu/sc520/sc520_timer.c @@ -81,7 +81,7 @@ void sc520_udelay(unsigned long usec) long temp;
temp = readw(&sc520_mmcr->swtmrmilli); - temp = readw(&sc520_mmcr->swtmrmicro); + temp += readw(&sc520_mmcr->swtmrmicro);
do { m += readw(&sc520_mmcr->swtmrmilli);

This avoids a compiler warning about unused variables.
Signed-off-by: Simon Glass sjg@chromium.org --- board/eNET/eNET.c | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-)
diff --git a/board/eNET/eNET.c b/board/eNET/eNET.c index 429fe1b..2f26470 100644 --- a/board/eNET/eNET.c +++ b/board/eNET/eNET.c @@ -178,11 +178,6 @@ void show_boot_progress(int val)
int last_stage_init(void) { - int minor; - int major; - - major = minor = 0; - outb(0x00, LED_LATCH_ADDRESS);
register_timer_isr(enet_timer_isr);

These are needed for generic relocation to function correctly.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/include/asm/reloc.h | 32 ++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/proc.S | 67 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 0 deletions(-) create mode 100644 arch/x86/include/asm/reloc.h create mode 100644 arch/x86/lib/proc.S
diff --git a/arch/x86/include/asm/reloc.h b/arch/x86/include/asm/reloc.h new file mode 100644 index 0000000..61e0887 --- /dev/null +++ b/arch/x86/include/asm/reloc.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * 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. + * + * 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 + */ + +#include <elf.h> + +int arch_elf_relocate_entry(Elf32_Addr *addr, Elf32_Word info, + Elf32_Sym *symtab, ulong reloc_off) +{ + /* TODO: if(ELF32_R_TYPE(ptr->r_info) != ... return -1 */ + if (*addr >= CONFIG_SYS_TEXT_BASE) + *addr += reloc_off; + + return 0; +} diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index d584aa4..ff5a864 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -27,6 +27,7 @@ LIB = $(obj)lib$(ARCH).o
SOBJS-$(CONFIG_SYS_PC_BIOS) += bios.o SOBJS-$(CONFIG_SYS_PCI_BIOS) += bios_pci.o +SOBJS-y += proc.o SOBJS-$(CONFIG_SYS_X86_REALMODE) += realmode_switch.o
COBJS-$(CONFIG_SYS_PC_BIOS) += bios_setup.o diff --git a/arch/x86/lib/proc.S b/arch/x86/lib/proc.S new file mode 100644 index 0000000..432ce0c --- /dev/null +++ b/arch/x86/lib/proc.S @@ -0,0 +1,67 @@ +/* + * U-boot - x86 processor assembler library + * + * (C) Copyright 2008-2011 + * Graeme Russ, graeme.russ@gmail.com + * + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + * + * 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. + * + * 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 + */ + +#include <config.h> +#include <version.h> +/* #include <asm/global_data.h> */ +#include <asm/processor-flags.h> +#include <generated/asm-offsets.h> + +.section .text +.code32 + + /* + * TODO: Sort out the argument passing and setup here. See C prototype + * for proc_call_board_init_r() + */ +.globl proc_call_board_init_r +.type proc_call_board_init_r, @function +proc_call_board_init_r: + /* + * SDRAM has been initialised, U-Boot code has been copied into + * RAM, BSS has been cleared and relocation adjustments have been + * made. It is now time to jump into the in-RAM copy of U-Boot + * + * %eax = Address of top of stack + * %edx = Address of Global Data + * %ecx = Base address of in-RAM copy of U-Boot + */ + + /* Setup stack in RAM */ + movl %eax, %esp + + /* Setup call address of in-RAM copy of board_init_r() */ + movl $board_init_r, %ebp + addl (GENERATED_GD_RELOC_OFF)(%edx), %ebp + + /* Setup parameters to board_init_r() */ + movl %edx, %eax + movl %ecx, %edx + + /* Jump to in-RAM copy of board_init_r() */ + call *%ebp

Include some symbols used by x86 and other architectures, then move x86 over to using this header file.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/include/asm/u-boot-arm.h | 4 ---- arch/x86/include/asm/u-boot-x86.h | 8 -------- arch/x86/lib/board.c | 1 + include/asm-generic/sections.h | 18 ++++++++++++++++++ 4 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h index 4ca75f9..7cfae9b 100644 --- a/arch/arm/include/asm/u-boot-arm.h +++ b/arch/arm/include/asm/u-boot-arm.h @@ -30,12 +30,8 @@ #define _U_BOOT_ARM_H_ 1
/* for the following variables, see start.S */ -extern ulong _bss_start_ofs; /* BSS start relative to _start */ -extern ulong _bss_end_ofs; /* BSS end relative to _start */ -extern ulong _end_ofs; /* end of image relative to _start */ extern ulong IRQ_STACK_START; /* top of IRQ stack */ extern ulong FIQ_STACK_START; /* top of FIQ stack */ -extern ulong _TEXT_BASE; /* code start */ extern ulong _datarel_start_ofs; extern ulong _datarelrolocal_start_ofs; extern ulong _datarellocal_start_ofs; diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 755f88a..d3e2f4c 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -24,14 +24,6 @@ #ifndef _U_BOOT_I386_H_ #define _U_BOOT_I386_H_ 1
-/* Exports from the Linker Script */ -extern ulong __text_start; -extern ulong __data_end; -extern ulong __rel_dyn_start; -extern ulong __rel_dyn_end; -extern ulong __bss_start; -extern ulong __bss_end; - /* cpu/.../cpu.c */ int x86_cpu_init_r(void); int cpu_init_r(void); diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 3d00f20..d4bfe88 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -42,6 +42,7 @@ #include <ide.h> #include <serial.h> #include <asm/u-boot-x86.h> +#include <asm-generic/sections.h> #include <elf.h>
#ifdef CONFIG_BITBANGMII diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 0dac424..f273a30 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -100,4 +100,22 @@ extern ulong _dynsym_start_ofs; /* End of the region to be relocated, as an offset form _start */ extern ulong _image_copy_end_ofs;
+extern ulong _bss_start_ofs; /* BSS start relative to _start */ +extern ulong _bss_end_ofs; /* BSS end relative to _start */ +extern ulong _end_ofs; /* end of image relative to _start */ + +extern ulong _TEXT_BASE; /* code start */ + +#else /* don't use offsets: */ + +/* Exports from the Linker Script */ +extern ulong __data_end; +extern ulong __rel_dyn_start; +extern ulong __rel_dyn_end; +extern ulong __bss_end; + +extern ulong _TEXT_BASE; /* code start */ + +#endif + #endif /* _ASM_GENERIC_SECTIONS_H_ */

These two fields are needed for x86.
Signed-off-by: Simon Glass sjg@chromium.org --- include/asm-generic/global_data.h | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 16fee5a..99750a8 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -50,6 +50,10 @@ typedef struct global_data { #endif unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid? */ +#ifdef CONFIG_X86 + unsigned long cpu_clk; /* CPU clock in Hz! */ + unsigned long bus_clk; +#endif unsigned long fb_base; /* base address of frame buffer */ #ifdef CONFIG_FSL_ESDHC unsigned long sdhc_clk;

We can use the declarations of __bss_start and _end from this header instead of declaring them locally.
Signed-off-by: Simon Glass sjg@chromium.org --- examples/standalone/stubs.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c index a6add6a..83454e3 100644 --- a/examples/standalone/stubs.c +++ b/examples/standalone/stubs.c @@ -203,16 +203,15 @@ void __attribute__((unused)) dummy(void) #include <_exports.h> }
-extern unsigned long __bss_start, _end; +#include <asm-generic/sections.h>
void app_startup(char * const *argv) { - unsigned char * cp = (unsigned char *) &__bss_start; + unsigned char *cp = &__bss_start;
/* Zero out BSS */ - while (cp < (unsigned char *)&_end) { + while (cp < &_end) *cp++ = 0; - }
#if defined(CONFIG_X86) /* x86 does not have a dedicated register for passing global_data */

These are available on other architecures, so add them on x86.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/include/asm/io.h | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 9b757d4..b12bdd8 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -234,4 +234,12 @@ static inline phys_addr_t virt_to_phys(void * vaddr) return (phys_addr_t)(vaddr); }
+/* + * TODO: The kernel offers some more advanced versions of barriers, it might + * have some advantages to use them instead of the simple one here. + */ +#define dmb() __asm__ __volatile__ ("" : : : "memory") +#define __iormb() dmb() +#define __iowmb() dmb() + #endif

Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/config.mk | 6 ------ arch/x86/include/asm/global_data.h | 6 ++++++ arch/x86/lib/Makefile | 2 ++ common/board_r.c | 3 +++ 4 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/arch/x86/config.mk b/arch/x86/config.mk index cb8865a..23cacff 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -48,9 +48,3 @@ NORMAL_LIBGCC = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) PREFIXED_LIBGCC = $(OBJTREE)/arch/$(ARCH)/lib/$(shell basename $(NORMAL_LIBGCC))
export USE_PRIVATE_LIBGCC=$(shell dirname $(PREFIXED_LIBGCC)) - -# We use legacy relocation for now -CONFIG_SYS_SKIP_RELOC := y - -# Move to unified board system later -CONFIG_SYS_LEGACY_BOARD := y diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 05a2139..d68447a 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -23,6 +23,8 @@
#ifndef __ASM_GBL_DATA_H #define __ASM_GBL_DATA_H + +#ifdef CONFIG_LEGACY_BOARD /* * The following data structure is placed in some memory wich is * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or @@ -81,4 +83,8 @@ extern gd_t *gd; gd_t *gd #endif
+#else /* CONFIG_SYS_LEGACY_BOARD */ +#include <asm-generic/global_data.h> +#endif + #endif /* __ASM_GBL_DATA_H */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index ff5a864..6c1cd64 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -31,7 +31,9 @@ SOBJS-y += proc.o SOBJS-$(CONFIG_SYS_X86_REALMODE) += realmode_switch.o
COBJS-$(CONFIG_SYS_PC_BIOS) += bios_setup.o +ifeq ($(CONFIG_SYS_LEGACY_BOARD),y) COBJS-y += board.o +endif COBJS-y += bootm.o COBJS-y += gcc.o COBJS-y += interrupts.o diff --git a/common/board_r.c b/common/board_r.c index bd656bd..2a01c3a 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -54,8 +54,11 @@ static int initr_reloc(void) */ static int initr_caches(void) { + /* TODO: sort out x86 code here */ +#ifndef CONFIG_X86 /* Enable caches */ enable_caches(); +#endif return 0; }

Now that x86 uses generic board, this code is not needed.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/include/asm/global_data.h | 61 ----- arch/x86/lib/Makefile | 2 - arch/x86/lib/board.c | 453 +----------------------------------- 3 files changed, 1 insertions(+), 515 deletions(-)
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index d68447a..2cd00b8 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -24,67 +24,6 @@ #ifndef __ASM_GBL_DATA_H #define __ASM_GBL_DATA_H
-#ifdef CONFIG_LEGACY_BOARD -/* - * The following data structure is placed in some memory wich is - * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or - * some locked parts of the data cache) to allow for a minimum set of - * global variables during system initialization (until we have set - * up the memory controller so that we can use RAM). - * - * Keep it *SMALL* and remember to set GENERATED_GBL_DATA_SIZE > sizeof(gd_t) - */ - -#ifndef __ASSEMBLY__ - -typedef struct global_data { - bd_t *bd; - unsigned long flags; - unsigned long baudrate; - unsigned long have_console; /* serial_init() was called */ -#ifdef CONFIG_PRE_CONSOLE_BUFFER - unsigned long precon_buf_idx; /* Pre-Console buffer index */ -#endif - unsigned long reloc_off; /* Relocation Offset */ - unsigned long load_off; /* Load Offset */ - unsigned long env_addr; /* Address of Environment struct */ - unsigned long env_valid; /* Checksum of Environment valid? */ - unsigned long cpu_clk; /* CPU clock in Hz! */ - unsigned long bus_clk; - unsigned long relocaddr; /* Start address of U-Boot in RAM */ - unsigned long start_addr_sp; /* start_addr_stackpointer */ - phys_size_t ram_size; /* RAM size */ - unsigned long reset_status; /* reset status register at boot */ - void **jt; /* jump table */ - char env_buf[32]; /* buffer for getenv() before reloc. */ -} gd_t; - -extern gd_t *gd; - -#endif - -/* - * Global Data Flags - */ -#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ -#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ -#define GD_FLG_SILENT 0x00004 /* Silent mode */ -#define GD_FLG_POSTFAIL 0x00008 /* Critical POST test failed */ -#define GD_FLG_POSTSTOP 0x00010 /* POST seqeunce aborted */ -#define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ -#define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ -#define GD_FLG_ENV_READY 0x00080 /* Environment imported into hash table */ - -#if 0 -#define DECLARE_GLOBAL_DATA_PTR -#else -#define XTRN_DECLARE_GLOBAL_DATA_PTR extern -#define DECLARE_GLOBAL_DATA_PTR XTRN_DECLARE_GLOBAL_DATA_PTR \ -gd_t *gd -#endif - -#else /* CONFIG_SYS_LEGACY_BOARD */ #include <asm-generic/global_data.h> -#endif
#endif /* __ASM_GBL_DATA_H */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 6c1cd64..ff5a864 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -31,9 +31,7 @@ SOBJS-y += proc.o SOBJS-$(CONFIG_SYS_X86_REALMODE) += realmode_switch.o
COBJS-$(CONFIG_SYS_PC_BIOS) += bios_setup.o -ifeq ($(CONFIG_SYS_LEGACY_BOARD),y) COBJS-y += board.o -endif COBJS-y += bootm.o COBJS-y += gcc.o COBJS-y += interrupts.o diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index d4bfe88..e7fd2a7 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -31,455 +31,4 @@ * MA 02111-1307 USA */
-#include <common.h> -#include <watchdog.h> -#include <command.h> -#include <stdio_dev.h> -#include <reloc.h> -#include <version.h> -#include <malloc.h> -#include <net.h> -#include <ide.h> -#include <serial.h> -#include <asm/u-boot-x86.h> -#include <asm-generic/sections.h> -#include <elf.h> - -#ifdef CONFIG_BITBANGMII -#include <miiphy.h> -#endif - -/* - * Pointer to initial global data area - * - * Here we initialize it. - */ -#undef XTRN_DECLARE_GLOBAL_DATA_PTR -#define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */ -DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR); - -/************************************************************************ - * Init Utilities * - ************************************************************************ - * Some of this code should be moved into the core functions, - * or dropped completely, - * but let's get it working (again) first... - */ -static int init_baudrate(void) -{ - gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); - return 0; -} - -static int display_banner(void) -{ - - printf("\n\n%s\n\n", version_string); - - return 0; -} - -static int display_dram_config(void) -{ - int i; - - puts("DRAM Configuration:\n"); - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - printf("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); - print_size(gd->bd->bi_dram[i].size, "\n"); - } - - return 0; -} - -#ifndef CONFIG_SYS_NO_FLASH -static void display_flash_config(ulong size) -{ - puts("Flash: "); - print_size(size, "\n"); -} -#endif - -/* - * Breath some life into the board... - * - * Initialize an SMC for serial comms, and carry out some hardware - * tests. - * - * The first part of initialization is running from Flash memory; - * its main purpose is to initialize the RAM so that we - * can relocate the monitor code to RAM. - */ - -/* - * All attempts to come up with a "common" initialization sequence - * that works for all boards and architectures failed: some of the - * requirements are just _too_ different. To get rid of the resulting - * mess of board dependend #ifdef'ed code we now make the whole - * initialization sequence configurable to the user. - * - * The requirements for any new initalization function is simple: it - * receives a pointer to the "global data" structure as it's only - * argument, and returns an integer return code, where 0 means - * "continue" and != 0 means "fatal error, hang the system". - */ -typedef int (init_fnc_t) (void); - -static int calculate_relocation_address(void); -static int copy_uboot_to_ram(void); -static int clear_bss(void); -static int do_elf_reloc_fixups(void); - -init_fnc_t *init_sequence_f[] = { - cpu_init_f, - board_early_init_f, - env_init, - init_baudrate, - serial_init, - console_init_f, - dram_init_f, - calculate_relocation_address, - copy_uboot_to_ram, - clear_bss, - do_elf_reloc_fixups, - - NULL, -}; - -init_fnc_t *init_sequence_r[] = { - cpu_init_r, /* basic cpu dependent setup */ - board_early_init_r, /* basic board dependent setup */ - dram_init, /* configure available RAM banks */ - interrupt_init, /* set up exceptions */ - timer_init, - display_banner, - display_dram_config, - - NULL, -}; - -gd_t *gd; - -static int calculate_relocation_address(void) -{ - ulong text_start = (ulong)&__text_start; - ulong bss_end = (ulong)&__bss_end; - ulong dest_addr; - ulong rel_offset; - - /* Calculate destination RAM Address and relocation offset */ - dest_addr = gd->ram_size; - dest_addr -= CONFIG_SYS_STACK_SIZE; - dest_addr -= (bss_end - text_start); - - /* - * Round destination address down to 16-byte boundary to keep - * IDT and GDT 16-byte aligned - */ - dest_addr &= ~15; - - rel_offset = dest_addr - text_start; - - gd->start_addr_sp = gd->ram_size; - gd->relocaddr = dest_addr; - gd->reloc_off = rel_offset; - - return 0; -} - -static int copy_uboot_to_ram(void) -{ - ulong *dst_addr = (ulong *)gd->relocaddr; - ulong *src_addr = (ulong *)&__text_start; - ulong *end_addr = (ulong *)&__data_end; - - while (src_addr < end_addr) - *dst_addr++ = *src_addr++; - - return 0; -} - -static int clear_bss(void) -{ - void *bss_start = &__bss_start; - void *bss_end = &__bss_end; - - ulong *dst_addr = (ulong *)(bss_start + gd->reloc_off); - ulong *end_addr = (ulong *)(bss_end + gd->reloc_off); - - while (dst_addr < end_addr) - *dst_addr++ = 0x00000000; - - return 0; -} - -static int do_elf_reloc_fixups(void) -{ - Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); - Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end); - - Elf32_Addr *offset_ptr_rom; - Elf32_Addr *offset_ptr_ram; - - /* The size of the region of u-boot that runs out of RAM. */ - uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; - - do { - /* Get the location from the relocation entry */ - offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; - - /* Check that the location of the relocation is in .text */ - if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE) { - - /* Switch to the in-RAM version */ - offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + - gd->reloc_off); - - /* Check that the target points into .text */ - if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE && - *offset_ptr_ram < - (CONFIG_SYS_TEXT_BASE + size)) { - *offset_ptr_ram += gd->reloc_off; - } - } - } while (re_src++ < re_end); - - return 0; -} - -/* Load U-Boot into RAM, initialize BSS, perform relocation adjustments */ -void board_init_f(ulong boot_flags) -{ - init_fnc_t **init_fnc_ptr; - - gd->flags = boot_flags; - - for (init_fnc_ptr = init_sequence_f; *init_fnc_ptr; ++init_fnc_ptr) { - if ((*init_fnc_ptr)() != 0) - hang(); - } - - gd->flags |= GD_FLG_RELOC; - - /* Enter the relocated U-Boot! */ - relocate_code(gd->start_addr_sp, gd, gd->relocaddr); - - /* NOTREACHED - relocate_code() does not return */ - while (1) - ; -} - -void board_init_r(gd_t *id, ulong dest_addr) -{ -#if defined(CONFIG_CMD_NET) - char *s; -#endif -#ifndef CONFIG_SYS_NO_FLASH - ulong size; -#endif - static bd_t bd_data; - static gd_t gd_data; - init_fnc_t **init_fnc_ptr; - - show_boot_progress(0x21); - - /* Global data pointer is now writable */ - gd = &gd_data; - memcpy(gd, id, sizeof(gd_t)); - - /* compiler optimization barrier needed for GCC >= 3.4 */ - __asm__ __volatile__("" : : : "memory"); - - gd->bd = &bd_data; - memset(gd->bd, 0, sizeof(bd_t)); - show_boot_progress(0x22); - - gd->baudrate = CONFIG_BAUDRATE; - - mem_malloc_init((((ulong)dest_addr - CONFIG_SYS_MALLOC_LEN)+3)&~3, - CONFIG_SYS_MALLOC_LEN); - - for (init_fnc_ptr = init_sequence_r; *init_fnc_ptr; ++init_fnc_ptr) { - if ((*init_fnc_ptr)() != 0) - hang(); - } - show_boot_progress(0x23); - -#ifdef CONFIG_SERIAL_MULTI - serial_initialize(); -#endif - -#ifndef CONFIG_SYS_NO_FLASH - /* configure available FLASH banks */ - size = flash_init(); - display_flash_config(size); - show_boot_progress(0x24); -#endif - - show_boot_progress(0x25); - - /* initialize environment */ - env_relocate(); - show_boot_progress(0x26); - - -#ifdef CONFIG_CMD_NET - /* IP Address */ - bd_data.bi_ip_addr = getenv_IPaddr("ipaddr"); -#endif - -#if defined(CONFIG_PCI) - /* - * Do pci configuration - */ - pci_init(); -#endif - - show_boot_progress(0x27); - - - stdio_init(); - - jumptable_init(); - - /* Initialize the console (after the relocation and devices init) */ - console_init_r(); - -#ifdef CONFIG_MISC_INIT_R - /* miscellaneous platform dependent initialisations */ - misc_init_r(); -#endif - -#if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE) - WATCHDOG_RESET(); - puts("PCMCIA:"); - pcmcia_init(); -#endif - -#if defined(CONFIG_CMD_KGDB) - WATCHDOG_RESET(); - puts("KGDB: "); - kgdb_init(); -#endif - - /* enable exceptions */ - enable_interrupts(); - show_boot_progress(0x28); - -#ifdef CONFIG_STATUS_LED - status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); -#endif - - udelay(20); - - /* Initialize from environment */ - load_addr = getenv_ulong("loadaddr", 16, load_addr); -#if defined(CONFIG_CMD_NET) - s = getenv("bootfile"); - - if (s != NULL) - copy_filename(BootFile, s, sizeof(BootFile)); -#endif - - WATCHDOG_RESET(); - -#if defined(CONFIG_CMD_IDE) - WATCHDOG_RESET(); - puts("IDE: "); - ide_init(); -#endif - -#if defined(CONFIG_CMD_SCSI) - WATCHDOG_RESET(); - puts("SCSI: "); - scsi_init(); -#endif - -#if defined(CONFIG_CMD_DOC) - WATCHDOG_RESET(); - puts("DOC: "); - doc_init(); -#endif - -#ifdef CONFIG_BITBANGMII - bb_miiphy_init(); -#endif -#if defined(CONFIG_CMD_NET) - WATCHDOG_RESET(); - puts("Net: "); - eth_initialize(gd->bd); -#endif - -#if (defined(CONFIG_CMD_NET)) && (0) - WATCHDOG_RESET(); -# ifdef DEBUG - puts("Reset Ethernet PHY\n"); -# endif - reset_phy(); -#endif - -#ifdef CONFIG_LAST_STAGE_INIT - WATCHDOG_RESET(); - /* - * Some parts can be only initialized if all others (like - * Interrupts) are up and running (i.e. the PC-style ISA - * keyboard). - */ - last_stage_init(); -#endif - - -#ifdef CONFIG_POST - post_run(NULL, POST_RAM | post_bootmode_get(0)); -#endif - - show_boot_progress(0x29); - - /* main_loop() can return to retry autoboot, if so just run it again. */ - for (;;) - main_loop(); - - /* NOTREACHED - no way out of command loop except booting */ -} - -void hang(void) -{ - puts("### ERROR ### Please RESET the board ###\n"); - for (;;) - ; -} - -unsigned long do_go_exec(ulong (*entry)(int, char * const []), - int argc, char * const argv[]) -{ - unsigned long ret = 0; - char **argv_tmp; - - /* - * x86 does not use a dedicated register to pass the pointer to - * the global_data, so it is instead passed as argv[-1]. By using - * argv[-1], the called 'Application' can use the contents of - * argv natively. However, to safely use argv[-1] a new copy of - * argv is needed with the extra element - */ - argv_tmp = malloc(sizeof(char *) * (argc + 1)); - - if (argv_tmp) { - argv_tmp[0] = (char *)gd; - - memcpy(&argv_tmp[1], argv, (size_t)(sizeof(char *) * argc)); - - ret = (entry) (argc, &argv_tmp[1]); - free(argv_tmp); - } - - return ret; -} - -void setup_pcat_compatibility(void) - __attribute__((weak, alias("__setup_pcat_compatibility"))); - -void __setup_pcat_compatibility(void) -{ -} +/* Code in this file has moved to board_f.c and board_r.c */

Dear Simon,
In message 1325054160-24894-1-git-send-email-sjg@chromium.org you wrote:
This series creates a generic board.c implementation which contains the essential functions of the various arch/xxx/lib/board.c files.
I'll be loking into this deeper when I'm back at work (i. e. starting with week 2 next year), but I'd like to make this comment as early as possible:
When making such changes, I _strongly_ recommend to use the Power architecture implementation as reference. There are a number of reasons for this, which I don't intend to explain in detail here and now (lack of time). But PPC is the most complete, longest living and most thoroughly designed architecture. Things that other architectures aquire only over time (relocation, cache support, FDT support, multiple busses [I2C, PCI, ...]) have "always" been supported by PPC.
I fear that unifying any architectures and not including PPC rightr from the beginning will result in additional efforts later, so please have a look is this can be changed.
Thanks.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Wed, Dec 28, 2011 at 9:30 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon,
In message 1325054160-24894-1-git-send-email-sjg@chromium.org you wrote:
This series creates a generic board.c implementation which contains the essential functions of the various arch/xxx/lib/board.c files.
I'll be loking into this deeper when I'm back at work (i. e. starting with week 2 next year), but I'd like to make this comment as early as possible:
When making such changes, I _strongly_ recommend to use the Power architecture implementation as reference. There are a number of reasons for this, which I don't intend to explain in detail here and now (lack of time). But PPC is the most complete, longest living and most thoroughly designed architecture. Things that other architectures aquire only over time (relocation, cache support, FDT support, multiple busses [I2C, PCI, ...]) have "always" been supported by PPC.
I fear that unifying any architectures and not including PPC rightr from the beginning will result in additional efforts later, so please have a look is this can be changed.
Thanks.
Yes that has been in the back of my mind. I have had a look through this but have not started a serious effort on it. There are quite a few extra bits. My main concern is that I cannot test PPC, but I will see if I can put together a patch in any case.
Regards, Simon
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@denx.de Cigarette, n.: A fire at one end, a fool at the other, and a bit of tobacco in between.

Hi Simon,
Sorry for the delay in reviewing this - I've been doing a lot of work on the x86 side of things. I now have a working solution to the board_init_f_r() / global data clobbering problem which involves having the gd 'variable' as a register like all other arch's. The solution is non-trivial and gd access is slightly more expensive than the vanilla variable approach, but it makes this a lot cleaner cross-arch wise...
Here's a hint ;)
static inline gd_t *get_fs_gd_ptr(void) { gd_t *gd_ptr;
asm volatile("fs movl 0, %0\n" : "=r" (gd_ptr));
return gd_ptr; }
#define gd get_fs_gd_ptr()
On 28/12/11 17:35, Simon Glass wrote:
This series creates a generic board.c implementation which contains the essential functions of the various arch/xxx/lib/board.c files.
What is the motivation for this change?
[snip]
I think that we can all agree that there is strong motivation for change.
However, I think this approach is not the right one - and I think the CFI driver backs me up. Your plan is to create generic code which you want ALL arches to cross over to, but you only look to migrate two initially and migrate the rest 'later'. This is similar to what happened with the CFI driver, and there are still boards with custom flash.c files which are completely redundant.
But, creating a single patch-set to migrate everyone in one go is going to be too massive a job to do in one go, and too prone to introducing breakage.
All the functions of board_init_f() and board_init_r() are broken into separate function calls so that they can easily be included or excluded for a particular architecture. It also makes it easier to adopt Graeme's initcall proposal later if desired.
I think we should look at this sooner rather than later. I've shown with x86 that the init sequence has three distinct phases:
1) Execute in flash using temporary RAM 2) Copy U-Boot from flash to RAM 3) Execute in RAM
My latest work now has all init functions having the same signature (i.e. void parameter returning int). For x86, there is a little 'magic' that needs to be done as gd is copied from temporary RAM to SDRAM, but for other arches using a dedicated register, this is otherwise trivial.
So instead of trying to pluck out something (relocation in this case) from the molasses of ten different board.c files and having to perform open-heart surgery on them all to get the code grafted in, I think we should approach it from the generic init sequence angle.
If we work each individual arch to use a generic init sequence (like the proposed x86 code) then the init processing naturally falls out as common code and the patch to realise this is trivial. From there, we can start to pull out common init code like init_baudrate() and hang() and change the function signatures of the functions that require wrappers and move some #ifdef's into more appropriate locations - One example in board.c:
#ifdef CONFIG_BITBANGMII int bb_miiphy_init_r(void) { bb_miiphy_init();
return 0; } #endif
Ouch!
The other big benefit is that you only touch one architecture at a time up until you 'pull the switch'. And when you do pull the switch, you should be factoring out identical code so the chances of breaking something should be vastly reduced. Take a look at the history of ARM relocation for example - that was constrained to one arch but still the amount of breakage was massive.
Generic relocation is used (see previous series) but now rather than calling relocate_code() to do everything, we call the individual relocation steps one by one. Again this makes it easier to leave things out, particularly for SPL.
Note that not all arches need and/or use ELF relocation - Attacking this first does not move towards unity of board.c
ARM is a relatively large board.c file and one which I can test, therefore I think it is a good target for this series. On the other hand, x86 is relatively small and simple, but different enough that it introduces a few issues to be solved. So I have chosen both ARM and x86 for this series.
The next target should probably be PowerPC, since it is large and has some additional features. I suspect we may want to leave some of these very architecture-specific functions in arch/powerpc/lib/board.c, taking out only the generic code. I haven't felt a strong need to do this for ARM/x86, but we could even go as far as putting the initcall list into the architecture-specific board file if the architecture adds a lot of unusual calls.
A generic global_data structure is also required. This might upset a few people. Here is my basic reasoning: most fields are the same, all architectures include and need it, most global_data.h files already have #ifdefs to select fields for a particular SOC, so it is hard to see why architecures are different in this area. We can perhaps add a way to put architecture-specific fields into a separate header file, but for now I have judged that to be counter-productive.
There was dicussion on the list about passing gd_t around as a parameter to pre-relocation init functions. I think this makes sense, but it can be done as a separate change, and this series does not require it.
This has been raised quite some time ago - The resulting code size increase is not worth it. x86 can now emulate the 'gd is a register' so gd is now available and writtable always on every arch. As I said before, gd access is slightly more expensive (one instruction) and initialising the gd pointer is _very_ expensive (rebuilding the Global Descriptor Table) but this only happens three times in total, so I am happy to accept the penalty for a unified architecture.
While this series needs to stand on its own (as with the link script cleanup series and the generic relocation series) the goal is the unification of the board init code. So I hope we can address issues with this in mind, rather than focusing too narrowly on particular ARM or x86 issues.
Comments welcome. Note that the x86 side of this still needs a fair bit of work, sorry.
The big issue I have is that we now have two RFC's which have major impacts on x86 and one of us is going to have to give way to the other :)
My patch set is mostly re-factoring and has no impact on anybody else and is practically complete - I'll do one last RFC, but I think it's already close to 'PATCH' status
Simon Glass (19): Introduce generic global_data Make relocation functions global Add basic initcall implementation define CONFIG_SYS_LEGACY_BOARD everywhere Add generic post-relocation board_r.c Add generic pre-relocation board_f.c Add spl load feature switch ARM over to generic board arm: Remove unused code in board.c, global_data.h Add CONFIG_SYS_SYM_OFFSETS to support offset symbols x86: Remove compiler warning in sc520_timer.c x86: Remove dead code in eNET x86: Add processor library and relocation functions Tidy up asm/generic sections.h to include x86 symbols Add fields required by x86 to global_data x86: Change stub example to use asm-generic/sections.h x86: Add initial memory barrier macros Bring in x86 to unified board architecture x86: Remove unused board/global_data code
There are several x86 patches which simply do not belong in this series (and some of which already have non-RFC patches submitted)
I honestly think we should get the x86 init sequence patches finalised first for several reasons:
- Because x86 is so small, it provides a good test-bed - ELF relocation was first finalised on x86 (it came and went with varying levels of success previously) - They bring x86 in line with other arches re: global data - They are now fully run-tested
Regards,
Graeme

Dear Graeme Russ,
In message 4EFDDD7D.50105@gmail.com you wrote:
I honestly think we should get the x86 init sequence patches finalised first for several reasons:
- Because x86 is so small, it provides a good test-bed - ELF relocation was first finalised on x86 (it came and went with varying levels of success previously)
- They bring x86 in line with other arches re: global data
- They are now fully run-tested
I agree with that.
Best regards,
Wolfgang Denk

Hi Graeme,
On Fri, Dec 30, 2011 at 7:49 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
Sorry for the delay in reviewing this - I've been doing a lot of work on the x86 side of things. I now have a working solution to the board_init_f_r() / global data clobbering problem which involves having the gd 'variable' as a register like all other arch's. The solution is non-trivial and gd access is slightly more expensive than the vanilla variable approach, but it makes this a lot cleaner cross-arch wise...
Here's a hint ;)
static inline gd_t *get_fs_gd_ptr(void) { gd_t *gd_ptr;
asm volatile("fs movl 0, %0\n" : "=r" (gd_ptr));
return gd_ptr; }
#define gd get_fs_gd_ptr()
On 28/12/11 17:35, Simon Glass wrote:
This series creates a generic board.c implementation which contains the essential functions of the various arch/xxx/lib/board.c files.
What is the motivation for this change?
[snip]
I think that we can all agree that there is strong motivation for change.
However, I think this approach is not the right one - and I think the CFI driver backs me up. Your plan is to create generic code which you want ALL arches to cross over to, but you only look to migrate two initially and migrate the rest 'later'. This is similar to what happened with the CFI driver, and there are still boards with custom flash.c files which are completely redundant.
But, creating a single patch-set to migrate everyone in one go is going to be too massive a job to do in one go, and too prone to introducing breakage.
Yes to some extent. However, my patch basically splits the two board_init_x() functions into parts, and puts them in a function table.
I don't think it is a huge job to do this for PowerPC also, and that seems to be the most feature-full architecture.
Also it does depend on expectations. I would hope that moving an architecture over would be a fairly small task:
- getting generic relocation working - adding functions for anything that is missing from board init code - removing things which don't work on the architecture? - worrying about differences in ordering between functions
All the functions of board_init_f() and board_init_r() are broken into separate function calls so that they can easily be included or excluded for a particular architecture. It also makes it easier to adopt Graeme's initcall proposal later if desired.
I think we should look at this sooner rather than later. I've shown with x86 that the init sequence has three distinct phases:
1) Execute in flash using temporary RAM 2) Copy U-Boot from flash to RAM 3) Execute in RAM
My latest work now has all init functions having the same signature (i.e. void parameter returning int). For x86, there is a little 'magic' that needs to be done as gd is copied from temporary RAM to SDRAM, but for other arches using a dedicated register, this is otherwise trivial.
So instead of trying to pluck out something (relocation in this case) from the molasses of ten different board.c files and having to perform open-heart surgery on them all to get the code grafted in, I think we should approach it from the generic init sequence angle.
If we work each individual arch to use a generic init sequence (like the proposed x86 code) then the init processing naturally falls out as common code and the patch to realise this is trivial. From there, we can start to pull out common init code like init_baudrate() and hang() and change the function signatures of the functions that require wrappers and move some #ifdef's into more appropriate locations - One example in board.c:
Well it seems like a lot of work to refactor each arch/xxx/board.c file into functions with a function pointer list, then later remove this code function by function.
My feeling is that with a generic board, it should hopefully be a fairly small amount of work for someone familiar with an architecture to find the bugs and patch the generic code to suit their architecture. It is something that needs to be done once, not every time there is a new patch removing (almost) common code.
#ifdef CONFIG_BITBANGMII int bb_miiphy_init_r(void) { bb_miiphy_init();
return 0; } #endif
Ouch!
The other big benefit is that you only touch one architecture at a time up until you 'pull the switch'. And when you do pull the switch, you should be factoring out identical code so the chances of breaking something should be vastly reduced. Take a look at the history of ARM relocation for example - that was constrained to one arch but still the amount of breakage was massive.
From previous discussions, if something is optional then the switch
will never happen. The code you are talking about is sometimes identical, sometimes slightly different. In some cases the order is different. I see many ways of introducing breakages. I do agree that doing one architecture at a time is best - with the proviso that we need to pick archs that have the most features (so ARM and PowerPC I suppose) to make sure we are not deluding ourselves as to the simplicity of the task.
So perhaps a generic board init that is the default can be switched off on board-by-board basic would be the right approach. Then we can flick the switch while providing for those affected to still get work done until bugs are reported and found?
Generic relocation is used (see previous series) but now rather than calling relocate_code() to do everything, we call the individual relocation steps one by one. Again this makes it easier to leave things out, particularly for SPL.
Note that not all arches need and/or use ELF relocation - Attacking this first does not move towards unity of board.c
It is a feature used by about half, and it does include the complexity of jumping from pre-reloc to post-reloc init. I think it was a reasonable first target.
ARM is a relatively large board.c file and one which I can test, therefore I think it is a good target for this series. On the other hand, x86 is relatively small and simple, but different enough that it introduces a few issues to be solved. So I have chosen both ARM and x86 for this series.
The next target should probably be PowerPC, since it is large and has some additional features. I suspect we may want to leave some of these very architecture-specific functions in arch/powerpc/lib/board.c, taking out only the generic code. I haven't felt a strong need to do this for ARM/x86, but we could even go as far as putting the initcall list into the architecture-specific board file if the architecture adds a lot of unusual calls.
A generic global_data structure is also required. This might upset a few people. Here is my basic reasoning: most fields are the same, all architectures include and need it, most global_data.h files already have #ifdefs to select fields for a particular SOC, so it is hard to see why architecures are different in this area. We can perhaps add a way to put architecture-specific fields into a separate header file, but for now I have judged that to be counter-productive.
There was dicussion on the list about passing gd_t around as a parameter to pre-relocation init functions. I think this makes sense, but it can be done as a separate change, and this series does not require it.
This has been raised quite some time ago - The resulting code size increase is not worth it. x86 can now emulate the 'gd is a register' so gd is now available and writtable always on every arch. As I said before, gd access is slightly more expensive (one instruction) and initialising the gd pointer is _very_ expensive (rebuilding the Global Descriptor Table) but this only happens three times in total, so I am happy to accept the penalty for a unified architecture.
OK, well it is a separate change as I said. I see a small code size increase also. Let's worry about that later.
While this series needs to stand on its own (as with the link script cleanup series and the generic relocation series) the goal is the unification of the board init code. So I hope we can address issues with this in mind, rather than focusing too narrowly on particular ARM or x86 issues.
Comments welcome. Note that the x86 side of this still needs a fair bit of work, sorry.
The big issue I have is that we now have two RFC's which have major impacts on x86 and one of us is going to have to give way to the other :)
Well I posted my x86 patches so they are not just sitting in the long grass on my machine. They are not complete, and I would likely need your input on these anyway.
My patch set is mostly re-factoring and has no impact on anybody else and is practically complete - I'll do one last RFC, but I think it's already close to 'PATCH' status
That's a separate series from my point of view. I can't comment on the wierd x96-isms in the series, but I did read through each patch and it all seems sensible to me.
Simon Glass (19): Introduce generic global_data Make relocation functions global Add basic initcall implementation define CONFIG_SYS_LEGACY_BOARD everywhere Add generic post-relocation board_r.c Add generic pre-relocation board_f.c Add spl load feature switch ARM over to generic board arm: Remove unused code in board.c, global_data.h Add CONFIG_SYS_SYM_OFFSETS to support offset symbols x86: Remove compiler warning in sc520_timer.c x86: Remove dead code in eNET x86: Add processor library and relocation functions Tidy up asm/generic sections.h to include x86 symbols Add fields required by x86 to global_data x86: Change stub example to use asm-generic/sections.h x86: Add initial memory barrier macros Bring in x86 to unified board architecture x86: Remove unused board/global_data code
There are several x86 patches which simply do not belong in this series (and some of which already have non-RFC patches submitted)
OK, these are the warnings I think. Probably I should build without -Werrors and try to ignore them!
I honestly think we should get the x86 init sequence patches finalised first for several reasons:
- Because x86 is so small, it provides a good test-bed - ELF relocation was first finalised on x86 (it came and went with varying levels of success previously) - They bring x86 in line with other arches re: global data - They are now fully run-tested
No disagreement there, and anyway as you can see the relocation stuff mostly came from your x86 code. It will provide a good template for getting x86 working properly with the generic board init.
What do you need from me to get that through?
Per Wolfgang's request to go with PPC as an early-adopter, this is somewhat in conflict, since as you say, x86 is less feature-full than ARM and much less than PowerPC.
Can anyone recommend a PowerPC board with a quick U-Boot program-run cycle that I can easily get that will let me try out things there?
Regards, Simon
Regards,
Graeme

Hi Simon,
On 31/12/11 13:02, Simon Glass wrote:
Hi Graeme,
On Fri, Dec 30, 2011 at 7:49 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
[snip]
However, I think this approach is not the right one - and I think the CFI driver backs me up. Your plan is to create generic code which you want ALL arches to cross over to, but you only look to migrate two initially and migrate the rest 'later'. This is similar to what happened with the CFI driver, and there are still boards with custom flash.c files which are completely redundant.
But, creating a single patch-set to migrate everyone in one go is going to be too massive a job to do in one go, and too prone to introducing breakage.
Yes to some extent. However, my patch basically splits the two board_init_x() functions into parts, and puts them in a function table.
Ah yes, looking a bit closer I see this now in patches 5 & 6. However, I think if you look at my patches 9, 10, 12 and 13 I'm doing essentially the same thing for x86. The difference is, I'm moving live code, rather than creating dead code then switching over. I personally do not think your approach is very safe - If there is a breakage, it is spread over multiple patches - With the 'move code around' approach, all breakages are confined to a single patch
I don't think it is a huge job to do this for PowerPC also, and that seems to be the most feature-full architecture.
I agree - The init architecture is the same, but the sequence is bigger (and not in the same order)
Also it does depend on expectations. I would hope that moving an architecture over would be a fairly small task:
- getting generic relocation working
- adding functions for anything that is missing from board init code
- removing things which don't work on the architecture?
- worrying about differences in ordering between functions
I see it as: 1) Rework the arch init sequence to be a pure list of 'int foo(void)' functions, adding helpers and wrappers where necessary 2) Switch over to use the generic init processing loop 3) Factor out common helpers and wrappers across all arches 4) Factor out common functionality (e.g. relocation) 5) After all arches are switched, remove wrappers by changing the function signature of the wrapped function 6) Move helpers into relevant driver/common source file
I think 1 & 2 need to be done for at least ARM, x86 and PPC before starting 3 & 4 and 1-4 needs to be done for all arches before doing 5 & 6
[snip]
If we work each individual arch to use a generic init sequence (like the proposed x86 code) then the init processing naturally falls out as common code and the patch to realise this is trivial. From there, we can start to pull out common init code like init_baudrate() and hang() and change the function signatures of the functions that require wrappers and move some #ifdef's into more appropriate locations - One example in board.c:
Well it seems like a lot of work to refactor each arch/xxx/board.c file into functions with a function pointer list, then later remove this code function by function.
Yes, it is more work, but it is intrinsically safer (and git bisect-able)
My feeling is that with a generic board, it should hopefully be a fairly small amount of work for someone familiar with an architecture to find the bugs and patch the generic code to suit their
You seem to admit that your approach can introduce bugs
architecture. It is something that needs to be done once, not every time there is a new patch removing (almost) common code.
The safer approach is to tackle each arch independently - Convert each board.c to something similar to what I have shown with x86 and test those arch-specific changes to make sure nothing has been broken. Then it is a trivial matter of checking that there are no incompatibilities between the arch and the common case (and adjusting as required) and switching over to the common case
[snip]
The other big benefit is that you only touch one architecture at a time up until you 'pull the switch'. And when you do pull the switch, you should be factoring out identical code so the chances of breaking something should be vastly reduced. Take a look at the history of ARM relocation for example - that was constrained to one arch but still the amount of breakage was massive.
From previous discussions, if something is optional then the switch
will never happen. The code you are talking about is sometimes identical, sometimes slightly different. In some cases the order is different. I see many ways of introducing breakages. I do agree that
The init sequence order is dictated arch-specifically through the init arrays which will (for the time being) remain in the arch specific board.c. But that is all arch/foo/lib/board.c will contain - init sequence arrays, no 'code'
doing one architecture at a time is best - with the proviso that we need to pick archs that have the most features (so ARM and PowerPC I suppose) to make sure we are not deluding ourselves as to the simplicity of the task.
ARM + PPC + x86 = 95% of the complexity. If we pull them off, the others are trivial cases.
So perhaps a generic board init that is the default can be switched off on board-by-board basic would be the right approach. Then we can flick the switch while providing for those affected to still get work done until bugs are reported and found?
Generic relocation is used (see previous series) but now rather than calling relocate_code() to do everything, we call the individual relocation steps one by one. Again this makes it easier to leave things out, particularly for SPL.
Note that not all arches need and/or use ELF relocation - Attacking this first does not move towards unity of board.c
It is a feature used by about half, and it does include the complexity of jumping from pre-reloc to post-reloc init. I think it was a reasonable first target.
It is an excellent first target after making the init sequence generic - skipping relocation is then trivial (you just don't include it in the init sequence)
[snip]
The big issue I have is that we now have two RFC's which have major impacts on x86 and one of us is going to have to give way to the other :)
Well I posted my x86 patches so they are not just sitting in the long grass on my machine. They are not complete, and I would likely need your input on these anyway.
Most of your patches are a subset of my complete init re-write (and credit where it is due, you initial relocation RFC was the catalyst - I wanted to make your life a little easier by simplifying things in x86-land)
My patch set is mostly re-factoring and has no impact on anybody else and is practically complete - I'll do one last RFC, but I think it's already close to 'PATCH' status
That's a separate series from my point of view. I can't comment on the wierd x96-isms in the series, but I did read through each patch and it all seems sensible to me.
Thanks, that is enough for me for now. I'll request a proper review when I submit the [PATCH] series
[snip]
There are several x86 patches which simply do not belong in this series (and some of which already have non-RFC patches submitted)
OK, these are the warnings I think. Probably I should build without -Werrors and try to ignore them!
Propagate them to the top of your list to get them out of the way. I need to add them to my series (with original attribution of course) or commit them as is (some need tweaking)
I honestly think we should get the x86 init sequence patches finalised first for several reasons:
- Because x86 is so small, it provides a good test-bed - ELF relocation
was first finalised on x86 (it came and went with varying levels of success previously)
- They bring x86 in line with other arches re: global data
- They are now fully run-tested
No disagreement there, and anyway as you can see the relocation stuff mostly came from your x86 code. It will provide a good template for getting x86 working properly with the generic board init.
What do you need from me to get that through?
Patience :) - I'll try to get a final series up this week
Per Wolfgang's request to go with PPC as an early-adopter, this is somewhat in conflict, since as you say, x86 is less feature-full than ARM and much less than PowerPC.
We need to get the PPC (plus ARM and x86) init sequence distilled to pure init loops before moving forward.
Can anyone recommend a PowerPC board with a quick U-Boot program-run cycle that I can easily get that will let me try out things there?
If all we are doing is moving and wrapping code, the review and test should be fairly straighfoward
Regards,
Graeme

Hi Graeme,
On Sat, Dec 31, 2011 at 3:52 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On 31/12/11 13:02, Simon Glass wrote:
Hi Graeme,
On Fri, Dec 30, 2011 at 7:49 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
[snip]
However, I think this approach is not the right one - and I think the CFI driver backs me up. Your plan is to create generic code which you want ALL arches to cross over to, but you only look to migrate two initially and migrate the rest 'later'. This is similar to what happened with the CFI driver, and there are still boards with custom flash.c files which are completely redundant.
But, creating a single patch-set to migrate everyone in one go is going to be too massive a job to do in one go, and too prone to introducing breakage.
Yes to some extent. However, my patch basically splits the two board_init_x() functions into parts, and puts them in a function table.
Ah yes, looking a bit closer I see this now in patches 5 & 6. However, I think if you look at my patches 9, 10, 12 and 13 I'm doing essentially the same thing for x86. The difference is, I'm moving live code, rather than creating dead code then switching over. I personally do not think your approach is very safe - If there is a breakage, it is spread over multiple patches - With the 'move code around' approach, all breakages are confined to a single patch
See my other email on this topic though - I feel that one test/fix cycle is better than testing every board for every little patch over an extended period.
I don't think it is a huge job to do this for PowerPC also, and that seems to be the most feature-full architecture.
I agree - The init architecture is the same, but the sequence is bigger (and not in the same order)
Yes that's what I'm finding.
Also it does depend on expectations. I would hope that moving an architecture over would be a fairly small task:
- getting generic relocation working
- adding functions for anything that is missing from board init code
- removing things which don't work on the architecture?
- worrying about differences in ordering between functions
I see it as: 1) Rework the arch init sequence to be a pure list of 'int foo(void)' functions, adding helpers and wrappers where necessary 2) Switch over to use the generic init processing loop 3) Factor out common helpers and wrappers across all arches 4) Factor out common functionality (e.g. relocation) 5) After all arches are switched, remove wrappers by changing the function signature of the wrapped function 6) Move helpers into relevant driver/common source file
I think 1 & 2 need to be done for at least ARM, x86 and PPC before starting 3 & 4 and 1-4 needs to be done for all arches before doing 5 & 6
OK yes we could do this. But I think the end result is different.
I am keen to create a single common/board_f.c implementation for pre-reloc init and common/board_r.c for post-reloc init. I believe where your approach ends up with with separate arch/xxx/board.c files still, with their own initcall list, and a number of private functions. Now this is better than where we are now, but my original complaint was that I want to be able to add features to a single place and have them work across all architectures. With your end-result I still need to figure out where to put the new feature in each initcall list and create 10 patches, one for each arch, to plumb it in.
IMO the ordering differences between architectures are mostly unnecessary - an artifact of forking the code - and we should aim to minimise these differences.
Putting everything in one file helps to clarify exactly what the differences are between archs, and discussions can take place as to why and whether this differences can be removed. If we accept that PPC is the one true way (in terms of U-Boot code base), then the job is to make other arch's code more like PPC. This is best done in one place I think.
After a bit of thought, I worry also that your approach will create an extended period of time where U-Boot is unstable, as patch are patch is added to refactor the code. Granted, many of these patches are small and the risk is small. But why bother? At the end we still have 10 different board files, lots of differences and no one willing to change anything because it requires an entire test cycle again.
Maybe I am being too ambitious here, but since everything started with PPC's board.c, I don't see why we shouldn't head back in that direction and just create a single file again. It does create a big test problem, but only once :-)
Anyway if we do go with what you propose I still think it is better than what we have.
[snip]
If we work each individual arch to use a generic init sequence (like the proposed x86 code) then the init processing naturally falls out as common code and the patch to realise this is trivial. From there, we can start to pull out common init code like init_baudrate() and hang() and change the function signatures of the functions that require wrappers and move some #ifdef's into more appropriate locations - One example in board.c:
Well it seems like a lot of work to refactor each arch/xxx/board.c file into functions with a function pointer list, then later remove this code function by function.
Yes, it is more work, but it is intrinsically safer (and git bisect-able)
Well I don't propose to create things which are not bisect-able. I think what you mean is that there will be a commit which switches over to generic board for an architecture, and board init before that patch is quite different from board init afterwards. Yes that's right. Once the patch is reviewed, testing and committed, presumably most boards will work fine. The exception will be the boards which have unique features and no one had time to check them. That problem is not unique to either approach. Future patches welcome :-)
My feeling is that with a generic board, it should hopefully be a fairly small amount of work for someone familiar with an architecture to find the bugs and patch the generic code to suit their
You seem to admit that your approach can introduce bugs
Yes I do. Both approaches introduce bugs. I think that is unavoidable so we should try to do this once and get the best result out of it that we can.
architecture. It is something that needs to be done once, not every time there is a new patch removing (almost) common code.
The safer approach is to tackle each arch independently - Convert each board.c to something similar to what I have shown with x86 and test those arch-specific changes to make sure nothing has been broken. Then it is a trivial matter of checking that there are no incompatibilities between the arch and the common case (and adjusting as required) and switching over to the common case
This switch-over is really no different from what I propose (except that I want to go further and have a single board file). It introduces the same bisect issue you mentioned, and I feel it doesn't really improve the situation. We have instability with each patch as we refactor the board init code on each arch, then instability when we switch over. Why not just have this pain once?
[snip]
The other big benefit is that you only touch one architecture at a time up until you 'pull the switch'. And when you do pull the switch, you should be factoring out identical code so the chances of breaking something should be vastly reduced. Take a look at the history of ARM relocation for example - that was constrained to one arch but still the amount of breakage was massive.
From previous discussions, if something is optional then the switch
will never happen. The code you are talking about is sometimes identical, sometimes slightly different. In some cases the order is different. I see many ways of introducing breakages. I do agree that
The init sequence order is dictated arch-specifically through the init arrays which will (for the time being) remain in the arch specific board.c. But that is all arch/foo/lib/board.c will contain - init sequence arrays, no 'code'
OK, see above. Better than what we have, for sure. I am hoping we can go further.
doing one architecture at a time is best - with the proviso that we need to pick archs that have the most features (so ARM and PowerPC I suppose) to make sure we are not deluding ourselves as to the simplicity of the task.
ARM + PPC + x86 = 95% of the complexity. If we pull them off, the others are trivial cases.
OK good.
So perhaps a generic board init that is the default can be switched off on board-by-board basic would be the right approach. Then we can flick the switch while providing for those affected to still get work done until bugs are reported and found?
Generic relocation is used (see previous series) but now rather than calling relocate_code() to do everything, we call the individual relocation steps one by one. Again this makes it easier to leave things out, particularly for SPL.
Note that not all arches need and/or use ELF relocation - Attacking this first does not move towards unity of board.c
It is a feature used by about half, and it does include the complexity of jumping from pre-reloc to post-reloc init. I think it was a reasonable first target.
It is an excellent first target after making the init sequence generic - skipping relocation is then trivial (you just don't include it in the init sequence)
Yes
[snip]
The big issue I have is that we now have two RFC's which have major impacts on x86 and one of us is going to have to give way to the other :)
Well I posted my x86 patches so they are not just sitting in the long grass on my machine. They are not complete, and I would likely need your input on these anyway.
Most of your patches are a subset of my complete init re-write (and credit where it is due, you initial relocation RFC was the catalyst - I wanted to make your life a little easier by simplifying things in x86-land)
Yes, they are a subset - but hopefully generic enough to work for any arch.
My patch set is mostly re-factoring and has no impact on anybody else and is practically complete - I'll do one last RFC, but I think it's already close to 'PATCH' status
That's a separate series from my point of view. I can't comment on the wierd x96-isms in the series, but I did read through each patch and it all seems sensible to me.
Thanks, that is enough for me for now. I'll request a proper review when I submit the [PATCH] series
OK
[snip]
There are several x86 patches which simply do not belong in this series (and some of which already have non-RFC patches submitted)
OK, these are the warnings I think. Probably I should build without -Werrors and try to ignore them!
Propagate them to the top of your list to get them out of the way. I need to add them to my series (with original attribution of course) or commit them as is (some need tweaking)
OK
I honestly think we should get the x86 init sequence patches finalised first for several reasons:
- Because x86 is so small, it provides a good test-bed - ELF relocation was first finalised on x86 (it came and went with varying levels of success previously) - They bring x86 in line with other arches re: global data - They are now fully run-tested
No disagreement there, and anyway as you can see the relocation stuff mostly came from your x86 code. It will provide a good template for getting x86 working properly with the generic board init.
What do you need from me to get that through?
Patience :) - I'll try to get a final series up this week
Per Wolfgang's request to go with PPC as an early-adopter, this is somewhat in conflict, since as you say, x86 is less feature-full than ARM and much less than PowerPC.
We need to get the PPC (plus ARM and x86) init sequence distilled to pure init loops before moving forward.
Well for now I'm going to continue looking at PPC init and seeing if I can roll into into the series. Whichever way we go it is a useful resource.
Can anyone recommend a PowerPC board with a quick U-Boot program-run cycle that I can easily get that will let me try out things there?
If all we are doing is moving and wrapping code, the review and test should be fairly straighfoward
Hmmm that's mostly what I am doing too, with the addition that I am trying to reason about the ordering of the code.
Regards, Simon
Regards,
Graeme

Hi Simon,
In case you haven't noticed (I did not Cc you or Wolfgang, sorry 'bout that) I've posted the cleaned up version of my x86 init refactoring...
On 02/01/12 10:48, Simon Glass wrote:
Hi Graeme,
On Sat, Dec 31, 2011 at 3:52 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On 31/12/11 13:02, Simon Glass wrote:
Hi Graeme,
On Fri, Dec 30, 2011 at 7:49 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
[snip]
Ah yes, looking a bit closer I see this now in patches 5 & 6. However, I think if you look at my patches 9, 10, 12 and 13 I'm doing essentially the same thing for x86. The difference is, I'm moving live code, rather than creating dead code then switching over. I personally do not think your approach is very safe - If there is a breakage, it is spread over multiple patches - With the 'move code around' approach, all breakages are confined to a single patch
See my other email on this topic though - I feel that one test/fix cycle is better than testing every board for every little patch over an extended period.
The problem is not one of how sparsely the test/fix cycles are spread over time, it is one of spreading the breakage over multiple patches - If you are replacing functionality then add the new functionality, add the hooks to use it and delete the old in a single patch. That way, if you change breaks something, the revert is trivial. If you multi-patch approach breaks something, the revert becomes more difficult.
I don't think it is a huge job to do this for PowerPC also, and that seems to be the most feature-full architecture.
I agree - The init architecture is the same, but the sequence is bigger (and not in the same order)
Yes that's what I'm finding.
Also it does depend on expectations. I would hope that moving an architecture over would be a fairly small task:
- getting generic relocation working
- adding functions for anything that is missing from board init code
- removing things which don't work on the architecture?
- worrying about differences in ordering between functions
I see it as:
- Rework the arch init sequence to be a pure list of 'int foo(void)'
functions, adding helpers and wrappers where necessary 2) Switch over to use the generic init processing loop 3) Factor out common helpers and wrappers across all arches 4) Factor out common functionality (e.g. relocation) 5) After all arches are switched, remove wrappers by changing the function signature of the wrapped function 6) Move helpers into relevant driver/common source file
I think 1 & 2 need to be done for at least ARM, x86 and PPC before starting 3 & 4 and 1-4 needs to be done for all arches before doing 5 & 6
OK yes we could do this. But I think the end result is different.
I am keen to create a single common/board_f.c implementation for pre-reloc init and common/board_r.c for post-reloc init. I believe where your approach ends up with with separate arch/xxx/board.c files still, with their own initcall list, and a number of private
Correct, but as a first step, the processing loop code is made common, leaving only the init arrays per-arch
functions. Now this is better than where we are now, but my original complaint was that I want to be able to add features to a single place and have them work across all architectures. With your end-result I still need to figure out where to put the new feature in each initcall list and create 10 patches, one for each arch, to plumb it in.
Agree, and my ultimate end goal (as per my previous initcall patch series) is to remove the per-arch init list as well...
IMO the ordering differences between architectures are mostly unnecessary - an artifact of forking the code - and we should aim to minimise these differences.
Putting everything in one file helps to clarify exactly what the differences are between archs, and discussions can take place as to why and whether this differences can be removed. If we accept that PPC is the one true way (in terms of U-Boot code base), then the job is to make other arch's code more like PPC. This is best done in one place I think.
I see two issues with your approach: 1) You want to take a 'big bang' approach and change every arch over in one set of patches. I admire your vision, but question you realism ;) I took one look across all the init sequences and fled in horror. Such a big-bang approach is sure to cause some _major_ board breakage 2) As Wolfgang has eluded to, a unified set of init arrays will be more #ifdef than code
After a bit of thought, I worry also that your approach will create an extended period of time where U-Boot is unstable, as patch are patch
How so - Take a look at my x86 patch series. It only impacts x86 and it can be easily tested. Other arches are going to be even easier as the most delicate part of my series was getting global data to behave properly. For the other arches, it will be a simple matter of moving code around. What I did for x86 was fold a single init function which was outside the init array into the array (and creating a helper or wrapper as needed) at a time in a series of small patches. I then squashed them all together
is added to refactor the code. Granted, many of these patches are small and the risk is small. But why bother? At the end we still have 10 different board files, lots of differences and no one willing to change anything because it requires an entire test cycle again.
Because what we end up with is 10 sets of init_f, init_f_r and init_r arrays - All the processing loop and entry points are common and all the helpers and wrappers have been factored out as far as possible.
So we have 10 sets of very clean code (statically initialised arrays) which we can look at side-by-side and decide what to do. This may be either: - Decide it's all too hard and keep them arch specific (but at least the processing code is now common) - Create unified arrays using #ifdefs - Distil them into a set of 'common for most' which we use as the default and have separate ones for the corner cases - Change the way we do things entirely
Your approach immediately goes for option #2 or #3 on the assumption that it is possible to do so - My approach may end up in exactly the same place, but if not, it's not a wasted effort
Maybe I am being too ambitious here, but since everything started with PPC's board.c, I don't see why we shouldn't head back in that direction and just create a single file again. It does create a big test problem, but only once :-)
No, it creates a _HUGE_ test problem - And what do we do with the corner cases that fail in weird and wonderful ways...
Anyway if we do go with what you propose I still think it is better than what we have.
[snip]
If we work each individual arch to use a generic init sequence (like the proposed x86 code) then the init processing naturally falls out as common code and the patch to realise this is trivial. From there, we can start to pull out common init code like init_baudrate() and hang() and change the function signatures of the functions that require wrappers and move some #ifdef's into more appropriate locations - One example in board.c:
Well it seems like a lot of work to refactor each arch/xxx/board.c file into functions with a function pointer list, then later remove this code function by function.
Yes, it is more work, but it is intrinsically safer (and git bisect-able)
Well I don't propose to create things which are not bisect-able. I
But you have - You create new functionality in one patch, add a number of patches, then finally use that new functionality in a later patch.
think what you mean is that there will be a commit which switches over to generic board for an architecture, and board init before that patch is quite different from board init afterwards. Yes that's right. Once the patch is reviewed, testing and committed, presumably most boards will work fine. The exception will be the boards which have unique features and no one had time to check them. That problem is not unique to either approach. Future patches welcome :-)
With my latest series, each patch made a functional change that was manifest _in that patch_ so I was able to step through each and every patch, building and running each one as I went (and just for the record, the first run through was a dead-set shocker - the gd patches had a fair bit more work to do)
You series does not do this - You can apply one patch, build, load and run and say 'yep, it still runs' but when you apply the next patch (or the next, or the next etc) and something breaks, it might not have been the last patch you applied that broke it. Specifically, patches 5 & 6 and then leap to patch 18 before we use that code in x86
My feeling is that with a generic board, it should hopefully be a fairly small amount of work for someone familiar with an architecture to find the bugs and patch the generic code to suit their
You seem to admit that your approach can introduce bugs
Yes I do. Both approaches introduce bugs. I think that is unavoidable so we should try to do this once and get the best result out of it that we can.
I comes down to identifying the exact patch that introduced the bug
architecture. It is something that needs to be done once, not every time there is a new patch removing (almost) common code.
The safer approach is to tackle each arch independently - Convert each board.c to something similar to what I have shown with x86 and test those arch-specific changes to make sure nothing has been broken. Then it is a trivial matter of checking that there are no incompatibilities between the arch and the common case (and adjusting as required) and switching over to the common case
This switch-over is really no different from what I propose (except that I want to go further and have a single board file). It introduces the same bisect issue you mentioned, and I feel it doesn't really
No it does not - each arch is migrated independently towards a common implementation (but that implementation is replicated in each arch) - So for each arch, up until the point were we say 'they are now the same' we can bisect a bug to a single patch in that arches migration path. Then we look at the code and say 'yep, they are all the same' and create the common code and switch them _all_ over in a single patch. This is bisectable at every step.
improve the situation. We have instability with each patch as we refactor the board init code on each arch, then instability when we switch over. Why not just have this pain once?
Because as soon as you break bisectability (is that even a word) your 'pain' is several orders of magnitude worse. A bisectable bug can be a simple revert. A non-bisectable bug requires a new patch which may introduce even more bugs
[snip]
The other big benefit is that you only touch one architecture at a time up until you 'pull the switch'. And when you do pull the switch, you should be factoring out identical code so the chances of breaking something should be vastly reduced. Take a look at the history of ARM relocation for example - that was constrained to one arch but still the amount of breakage was massive.
From previous discussions, if something is optional then the switch
will never happen. The code you are talking about is sometimes identical, sometimes slightly different. In some cases the order is different. I see many ways of introducing breakages. I do agree that
The init sequence order is dictated arch-specifically through the init arrays which will (for the time being) remain in the arch specific board.c. But that is all arch/foo/lib/board.c will contain - init sequence arrays, no 'code'
OK, see above. Better than what we have, for sure. I am hoping we can go further.
And so am I - I have not given up on initcall yet ;) (actually, I have an idea but I'll start a new thread to discuss)
[snip]
Regards,
Graeme

Dear Graeme Russ,
In message 4F019473.8000204@gmail.com you wrote:
The problem is not one of how sparsely the test/fix cycles are spread over time, it is one of spreading the breakage over multiple patches - If you are replacing functionality then add the new functionality, add the hooks to use it and delete the old in a single patch. That way, if you change breaks something, the revert is trivial. If you multi-patch approach breaks something, the revert becomes more difficult.
True. Especially as it's likely that different patches will break different boards, so there will not even be a chance so revert.
Well I don't propose to create things which are not bisect-able. I
But you have - You create new functionality in one patch, add a number of patches, then finally use that new functionality in a later patch.
This is what I fear as well.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Mon, Jan 2, 2012 at 6:46 AM, Wolfgang Denk wd@denx.de wrote:
Dear Graeme Russ,
In message 4F019473.8000204@gmail.com you wrote:
The problem is not one of how sparsely the test/fix cycles are spread over time, it is one of spreading the breakage over multiple patches - If you are replacing functionality then add the new functionality, add the hooks to use it and delete the old in a single patch. That way, if you change breaks something, the revert is trivial. If you multi-patch approach breaks something, the revert becomes more difficult.
True. Especially as it's likely that different patches will break different boards, so there will not even be a chance so revert.
The only option would be to have a way to use the legacy code for particular boards (say a CONFIG option) until they are fixed. Not entirely satisfactory. Of course this could happen with either approach, and reverts become impossible when further patches are layered on top.
Well I don't propose to create things which are not bisect-able. I
But you have - You create new functionality in one patch, add a number of patches, then finally use that new functionality in a later patch.
This is what I fear as well.
Well let's see how we go with the incremental approach - hopefully we can get the same result with less pain and risk, and not too much work.
Regards, Simon
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@denx.de Disc space - the final frontier!

Dear Simon Glass,
In message CAPnjgZ2jS8kzCt06LbYnXSyEKm6ck8apm=P1YqqDtnZ0+q9dhw@mail.gmail.com you wrote:
Well let's see how we go with the incremental approach - hopefully we can get the same result with less pain and risk, and not too much work.
Did you miss my proposal not to change the existing coe for all boards, but to provide anew implementation and convert boards one by one? What do you think about such an approach?
Best regards,
Wolfgang Denk

Hi Wolfgang,
On 03/01/12 19:12, Wolfgang Denk wrote:
Dear Simon Glass,
In message CAPnjgZ2jS8kzCt06LbYnXSyEKm6ck8apm=P1YqqDtnZ0+q9dhw@mail.gmail.com you wrote:
Well let's see how we go with the incremental approach - hopefully we can get the same result with less pain and risk, and not too much work.
Did you miss my proposal not to change the existing coe for all boards, but to provide anew implementation and convert boards one by one? What do you think about such an approach?
My idea was to migrate each arch to the 'pure processing loops' implementation I have just posted for x86. We can then factor out the processing loop code into common code leaving just the init function arrays in arch/foo/lib/board.c
We can then look at how to deal with the disparate init sequences - I'm going to have a look at my new 'initcall' proposal to see if that is viable - If so, we auto generate init_sequence.c
Regards,
Graeme

Hi Wolfgang,
On Tue, Jan 3, 2012 at 12:12 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message CAPnjgZ2jS8kzCt06LbYnXSyEKm6ck8apm=P1YqqDtnZ0+q9dhw@mail.gmail.com you wrote:
Well let's see how we go with the incremental approach - hopefully we can get the same result with less pain and risk, and not too much work.
Did you miss my proposal not to change the existing coe for all boards, but to provide anew implementation and convert boards one by one? What do you think about such an approach?
Sorry I must have misread this as 'architecture' instead of 'board'. I suppose this would work since there is a simple CONFIG switch to move over.
The concern with doing this for a whole architecture was the board breakages, and this idea would avoid that. I wonder what would be the incentive for boards to move over? Perhaps eventually it could be the default, or we could discourage patches to the old code.
I have brought in PPC to board_f.c and board_r.c but not dealt with relocation. Once I have done that, gone through the new x86 series again and MAKEALL doesn't scream too loudly I'll do another RFC along these lines.
If Graham can move his initcall stuff along too then we can also get rid of the #ifdefs, which it IMO the main ugliness with my RFC.
Regards, Simon
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@denx.de "The X11 source code style is ATROCIOUS and should not be used as a model." - Doug Gwyn

Dear Simon Glass,
In message CAPnjgZ3592m_m=TMaFptwzO+_O94veYkVRFFdGPP599igefNyg@mail.gmail.com you wrote:
I have brought in PPC to board_f.c and board_r.c but not dealt with relocation. Once I have done that, gone through the new x86 series again and MAKEALL doesn't scream too loudly I'll do another RFC along these lines.
I'm seriously concerned about you insisting to include relocation here. This has nothign to do with it. Leave that out.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Tue, Jan 3, 2012 at 2:35 PM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message CAPnjgZ3592m_m=TMaFptwzO+_O94veYkVRFFdGPP599igefNyg@mail.gmail.com you wrote:
I have brought in PPC to board_f.c and board_r.c but not dealt with relocation. Once I have done that, gone through the new x86 series again and MAKEALL doesn't scream too loudly I'll do another RFC along these lines.
I'm seriously concerned about you insisting to include relocation here. This has nothign to do with it. Leave that out.
I'm not insisting, only that I have already done a series for generic relocation so figured this new series would come second. I did signal this right at the beginning when suggesting the approach:
http://lists.denx.de/pipermail/u-boot/2011-November/109987.html
Anyway, leaving out relocation is easier so I will rebase this series on top of master instead.
Regards, Simon
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@denx.de "When the only tool you have is a hammer, you tend to treat everything as if it were a nail." - Abraham Maslow

Hi Graham,
On Mon, Jan 2, 2012 at 3:26 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
In case you haven't noticed (I did not Cc you or Wolfgang, sorry 'bout that) I've posted the cleaned up version of my x86 init refactoring...
Yes I see it - thats great thanks. I will go through it and compare.
[big snip]
functions. Now this is better than where we are now, but my original complaint was that I want to be able to add features to a single place and have them work across all architectures. With your end-result I still need to figure out where to put the new feature in each initcall list and create 10 patches, one for each arch, to plumb it in.
Agree, and my ultimate end goal (as per my previous initcall patch series) is to remove the per-arch init list as well...
Well since it seems we are going for the same goal, and you are actively submitting patches towards it, I'm very happy. I mostly agree with your points, so will not respond bit by bit. The easiest route to the goal is the right one, so let's run with what you propose and see how we go. Thanks for taking it up.
[another big snip]
I had a go at bringing PPC into the generic board patches. Apart from the cloud of #ifdefs as expected it is not too bad. And those can be dealt with by initcalls.
Am hoping we can get there soon!
Regards, Simon
Regards,
Graeme

Dear Simon Glass,
In message CAPnjgZ1Zim6=u3rLcnAKE-0Bw3sO_hRY+U67jkpkNoNi8g7ctw@mail.gmail.com you wrote:
Also it does depend on expectations. I would hope that moving an architecture over would be a fairly small task:
- getting generic relocation working
I don;t see why this would be a direct prerequisite here. We want to have that, no boubt about that. But it appears to be an unrelated change to me.
- adding functions for anything that is missing from board init code
"anything that is missing from board init code" ?
- removing things which don't work on the architecture?
That would probably reander systems broken that need these things?
- worrying about differences in ordering between functions
This is indeed the biggest issue.
Keep in mind that my original ida of providing a function call table was to allow to define this table in a board specific way (i. e. in the board config file).
[Not that this idea found many friends...]
pull out common init code like init_baudrate() and hang() and change the function signatures of the functions that require wrappers and move some #ifdef's into more appropriate locations - One example in board.c:
Well it seems like a lot of work to refactor each arch/xxx/board.c file into functions with a function pointer list, then later remove this code function by function.
Would that really be a clever approach?
My feeling is that with a generic board, it should hopefully be a fairly small amount of work for someone familiar with an architecture to find the bugs and patch the generic code to suit their architecture. It is something that needs to be done once, not every time there is a new patch removing (almost) common code.
It is definitely not that easy. You fix one thing here, and break another board there. Ideally you would have to re-test any change on _all_ boards.
From previous discussions, if something is optional then the switch will never happen. The code you are talking about is sometimes identical, sometimes slightly different. In some cases the order is different. I see many ways of introducing breakages. I do agree that
And I bet most of them _will_ introduce breakages.
doing one architecture at a time is best - with the proviso that we need to pick archs that have the most features (so ARM and PowerPC I suppose) to make sure we are not deluding ourselves as to the simplicity of the task.
I would suggest to attempt to merge ARM into PPC.
So perhaps a generic board init that is the default can be switched off on board-by-board basic would be the right approach. Then we can flick the switch while providing for those affected to still get work done until bugs are reported and found?
Heh! Board specific init tables!
Note that not all arches need and/or use ELF relocation - Attacking this first does not move towards unity of board.c
It is a feature used by about half, and it does include the complexity of jumping from pre-reloc to post-reloc init. I think it was a reasonable first target.
What exactly is the problem here?
Per Wolfgang's request to go with PPC as an early-adopter, this is
No. It's the other way round. PPC is what should be adopted to.
Can anyone recommend a PowerPC board with a quick U-Boot program-run cycle that I can easily get that will let me try out things there?
Define "get easily".
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Dec 31, 2011 at 5:54 PM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message CAPnjgZ1Zim6=u3rLcnAKE-0Bw3sO_hRY+U67jkpkNoNi8g7ctw@mail.gmail.com you wrote:
Also it does depend on expectations. I would hope that moving an architecture over would be a fairly small task:
- getting generic relocation working
I don;t see why this would be a direct prerequisite here. We want to have that, no boubt about that. But it appears to be an unrelated change to me.
I don't think it's essential, but it is desirable, which I why it is on the list.
- adding functions for anything that is missing from board init code
"anything that is missing from board init code" ?
By that I mean that if the architecture has its own little things which aren't supported by generic board init, then these would need to be worked into the generic board init somehow, perhaps initially with a new function in the initcall list.
- removing things which don't work on the architecture?
That would probably reander systems broken that need these things?
Sorry for being so vague. What I mean is that if an arch does not support a feature, then we don't want to call the init functions for it on that architecture. Sometimes this is handled automatically - e.g. if an arch does not support CONFIG_POST then the generic board init code will skip this anyway. But there may be other cases where features available in the generic board init cannot be supported in all archs.
- worrying about differences in ordering between functions
This is indeed the biggest issue.
Keep in mind that my original ida of providing a function call table was to allow to define this table in a board specific way (i. e. in the board config file).
[Not that this idea found many friends...]
With this series I have moved over to purely having a function call table, with no actual init code in board_init_f() and board_init_r().
Having done this, I have found that the list of functions is very long, So we probably don't want boards to duplicate this list and #ifdefs may be the lesser of two evils. If we can move to Graham' initcall idea (basically using the linker to create the list of initcalls for pre- and post-reloc) then it becomes possible to boards to insert things in the init sequence without #ifdefs in commong/board.f/r.c.
For now I have tried to simply move the code into separate functions, since this makes it easier to compare against the original code in the arch/xxx/lib/board.c files, to make sure nothing is left out and the ordering is OK.
pull out common init code like init_baudrate() and hang() and change the function signatures of the functions that require wrappers and move some #ifdef's into more appropriate locations - One example in board.c:
Well it seems like a lot of work to refactor each arch/xxx/board.c file into functions with a function pointer list, then later remove this code function by function.
Would that really be a clever approach?
I'm not convinced it is the best idea. A trivial change of just removing duplicated code from all the archs and inserting it into generic board should be safe enough. But is that really a common case? I have found lots of subtle differences that need to be worked out, and there is the ordering to worry about. Every time there is a patch we need to re-test all boards. It might be easier to just create a generic board implementation one, and then test it once on each board, rather than testing on each board with every patch. Of course every time you patch generic board you might introduce a breakage in an existing (previously working) board, but that is the normal situation with development so I don't see a problem there.
Perhaps the biggest problem is the difficulty of testing, and if we can avoid months of little patches (each one potentially breaking lots of boards at run-time) then I would prefer that.
My feeling is that with a generic board, it should hopefully be a fairly small amount of work for someone familiar with an architecture to find the bugs and patch the generic code to suit their architecture. It is something that needs to be done once, not every time there is a new patch removing (almost) common code.
It is definitely not that easy. You fix one thing here, and break another board there. Ideally you would have to re-test any change on _all_ boards.
Well I suppose that's what I'm saying. Doing this once, accepting that some boards will thereby be broken, and then accepting patches to fix them feels easier than trying to keep everything working through a long series of little changes.
From previous discussions, if something is optional then the switch will never happen. The code you are talking about is sometimes identical, sometimes slightly different. In some cases the order is different. I see many ways of introducing breakages. I do agree that
And I bet most of them _will_ introduce breakages.
doing one architecture at a time is best - with the proviso that we need to pick archs that have the most features (so ARM and PowerPC I suppose) to make sure we are not deluding ourselves as to the simplicity of the task.
I would suggest to attempt to merge ARM into PPC.
Yes I hear you. I have had a crack at that with pre-reloc init. It's not exactly a thing of beauty but it isn't too bad. What I really like about having everything in one file (#ifdefs and all) is that you can quickly see where there are unnecessary arch differences, and refactor them.
So perhaps a generic board init that is the default can be switched off on board-by-board basic would be the right approach. Then we can flick the switch while providing for those affected to still get work done until bugs are reported and found?
Heh! Board specific init tables!
See above - I vote for Graham's initcall stuff - I believe the main concern was figuring out the init order and perhaps a little objdump | grep | awk System.map script would do the job here.
Note that not all arches need and/or use ELF relocation - Attacking this first does not move towards unity of board.c
It is a feature used by about half, and it does include the complexity of jumping from pre-reloc to post-reloc init. I think it was a reasonable first target.
What exactly is the problem here?
The problem is the code duplication inherent in relocation - each architecture has its own way of doing it, but really it can mostly be written generically in C. ARM is even worse with each CPU implementing essentially the same code!
Per Wolfgang's request to go with PPC as an early-adopter, this is
No. It's the other way round. PPC is what should be adopted to.
Yes I can see that PPC is a superset, or at least contains the most features. I will continue to look at this.
Can anyone recommend a PowerPC board with a quick U-Boot program-run cycle that I can easily get that will let me try out things there?
Define "get easily".
Well, perhaps buy for around $500 or so and get it shipped to California to arrive this week/early next?
Regards, Simon
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@denx.de People have one thing in common: they are all different.

Dear Simon Glass,
In message CAPnjgZ1eutEboyvEtYcxcZcv=1Z_3tKq_45wBrgNdPsnxRth3A@mail.gmail.com you wrote:
- getting generic relocation working
I don;t see why this would be a direct prerequisite here. =A0We want to have that, no boubt about that. =A0But it appears to be an unrelated change to me.
I don't think it's essential, but it is desirable, which I why it is on the list.
I recommend to put this on a different list. Please keep changes orthogonal and restict this discussion and patch series to things dealing with the normalization of the board init code.
This is complicated enough, and it does not good to include additional, unrelated tasks.
- adding functions for anything that is missing from board init code
"anything that is missing from board init code" ?
By that I mean that if the architecture has its own little things which aren't supported by generic board init, then these would need to be worked into the generic board init somehow, perhaps initially with a new function in the initcall list.
Such an approach will most probable result in a mess of code that is even more dificult to maintain than the current split we have now.
- removing things which don't work on the architecture?
That would probably reander systems broken that need these things?
Sorry for being so vague. What I mean is that if an arch does not support a feature, then we don't want to call the init functions for it on that architecture. Sometimes this is handled automatically - e.g. if an arch does not support CONFIG_POST then the generic board init code will skip this anyway. But there may be other cases where features available in the generic board init cannot be supported in all archs.
This is the same problem as above, right? Each architecture, and actually each board may or may not require certain initializations, and actually may require them to happen in a certain order (which may be different from other boards).
Keep in mind that my original ida of providing a function call table was to allow to define this table in a board specific way (i. e. in the board config file).
[Not that this idea found many friends...]
With this series I have moved over to purely having a function call table, with no actual init code in board_init_f() and board_init_r().
This was the original plan.
Having done this, I have found that the list of functions is very long, So we probably don't want boards to duplicate this list and #ifdefs may be the lesser of two evils. If we can move to Graham'
I don't really see this as an practical approach. Did you look at the PPC code? init_sequence[] has a total of 29 entries, "decorated" with 21 conditionals. If we merge in ARM and x86, we will have a mess nobody is able to understand.
For now I have tried to simply move the code into separate functions, since this makes it easier to compare against the original code in the arch/xxx/lib/board.c files, to make sure nothing is left out and the ordering is OK.
Agreed.
I'm not convinced it is the best idea. A trivial change of just removing duplicated code from all the archs and inserting it into generic board should be safe enough. But is that really a common case? I have found lots of subtle differences that need to be worked out, and there is the ordering to worry about. Every time there is a patch we need to re-test all boards. It might be easier to just create a generic board implementation one, and then test it once on each board, rather than testing on each board with every patch. Of course every time you patch generic board you might introduce a breakage in an existing (previously working) board, but that is the normal situation with development so I don't see a problem there.
Perhaps the biggest problem is the difficulty of testing, and if we can avoid months of little patches (each one potentially breaking lots of boards at run-time) then I would prefer that.
I am not sure that the whole approach makes sense. The resulkting mess of #ifdef's is not there because people didn't care, but because of very specific requirements of specific hardware, that - at least given the tools of the respective point of time - could not be solved more efficiently.
I see two options here:
- We can take the existing code and try to unify it, and make all boards (including a large number of EOLed and unmaintained ones) to that new code base.
This will be a lot of work, and the resulting code will probably messy again.
- We could as well try to come up with a new, cleaned up implementa- tion that maybe doesn't fit all, but only 80 or 90% of the existing boards. We could then (1) convert existing code step by step to the new implementation and (2) accept new submissions only when using the new code.
There may be a number of boards where conversion is non trivial, or where nobody is willing or able to perform the changes and / or the testing. My gut feeling tis that this would be a relatively small number of boards, and mostly old and unmaintained ones. We might give them some grace period and then remove them.
Well I suppose that's what I'm saying. Doing this once, accepting that some boards will thereby be broken, and then accepting patches to fix them feels easier than trying to keep everything working through a long series of little changes.
You appear to assume that onlly a small percentage of boards would be broken. My expectations are different. Intentionally causing breakage may be useful here and there, but I don;t think it;s the right thing here.
It is a feature used by about half, and it does include the complexity of jumping from pre-reloc to post-reloc init. I think it was a reasonable first target.
What exactly is the problem here?
The problem is the code duplication inherent in relocation - each architecture has its own way of doing it, but really it can mostly be written generically in C. ARM is even worse with each CPU implementing essentially the same code!
I suggect we leave relocation out of this discussion here. It is an area that needs to be cleaned up, definitely. But it is another, unrelated topic.
Best regards,
Wolfgang Denk
participants (4)
-
Andreas Bießmann
-
Graeme Russ
-
Simon Glass
-
Wolfgang Denk