[U-Boot] [PATCH 01/10] arm: Compile cache_disable() with -O2 to avoid failure

It is good to have these functions written in C instead of assembler, but with -O0 the cache_disable() function doesn't return. Rather than revert to assembler, this fix just forces this to be built with -O2.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/lib/cache-cp15.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c index 939de10..8f8385d 100644 --- a/arch/arm/lib/cache-cp15.c +++ b/arch/arm/lib/cache-cp15.c @@ -110,6 +110,16 @@ static void cache_enable(uint32_t cache_bit) set_cr(reg | cache_bit); }
+/* + * Big hack warning! + * + * Devs like to compile with -O0 to get a nice debugging illusion. But this + * function does not survive that since -O0 causes the compiler to read the + * PC back from the stack after the dcache flush. Might it be possible to fix + * this by flushing the write buffer? + */ +static void cache_disable(uint32_t cache_bit) __attribute__ ((optimize(2))); + /* cache_bit must be either CR_I or CR_C */ static void cache_disable(uint32_t cache_bit) {

From: Arun Mankuzhi arun.m@samsung.com
In Cortex-A15 architecture, when we run cache invalidate the cache clean operation executes automatically. So if there are any dirty cache lines before disabling the L2 cache these will be synchronized with the main memory when invalidate_dcache_all() runs in the last part of U-boot
The two functions after flush_dcache_all is using the stack. So this data will be on the cache. After disable when invalidate is called the data will be flushed from cache to memory. This corrupts the stack in invalida_dcache_all. So this change is required to avoid the u-boot hang.
So flush has to be done just before clearing CR_C bit
Signed-off-by: Arun Mankuzhi arun.m@samsung.com Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/lib/cache-cp15.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c index 8f8385d..03b9c80 100644 --- a/arch/arm/lib/cache-cp15.c +++ b/arch/arm/lib/cache-cp15.c @@ -134,8 +134,11 @@ static void cache_disable(uint32_t cache_bit) return; /* if disabling data cache, disable mmu too */ cache_bit |= CR_M; - flush_dcache_all(); } + reg = get_cr(); + cp_delay(); + if (cache_bit == (CR_C | CR_M)) + flush_dcache_all(); set_cr(reg & ~cache_bit); } #endif

From: Gabe Black gabeblack@chromium.org
It may be necessary to know where the TLB area ends as well as where it starts. This allows board code to complete a secure memory erase without destroying the page tables.
Signed-off-by: Gabe Black gabeblack@google.com Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/include/asm/global_data.h | 1 + arch/arm/lib/board.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 2b9af93..41a26ed 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -73,6 +73,7 @@ typedef struct global_data { unsigned long reloc_off; #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) unsigned long tlb_addr; + unsigned long tlb_size; #endif const void *fdt_blob; /* Our device tree, NULL if none */ void **jt; /* jump table */ diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 92cad9a..6e048aa 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -346,13 +346,14 @@ void board_init_f(ulong bootflag)
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) /* reserve TLB table */ - addr -= (4096 * 4); + gd->tlb_size = 4096 * 4; + addr -= gd->tlb_size;
/* round down to next 64 kB limit */ addr &= ~(0x10000 - 1);
gd->tlb_addr = addr; - debug("TLB table at: %08lx\n", addr); + debug("TLB table from %08lx to %08lx\n", addr, addr + gd->tlb_size); #endif
/* round down to next 4 kB limit */

We want to use the fdt inside board_early_init_f(), so check for its presence earlier in the pre-reloc init sequence.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/lib/board.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 6e048aa..2ec6a43 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -226,13 +226,12 @@ int arch_cpu_init(void)
init_fnc_t *init_sequence[] = { arch_cpu_init, /* basic arch cpu dependent setup */ - -#if defined(CONFIG_BOARD_EARLY_INIT_F) - board_early_init_f, -#endif #ifdef CONFIG_OF_CONTROL fdtdec_check_fdt, #endif +#if defined(CONFIG_BOARD_EARLY_INIT_F) + board_early_init_f, +#endif timer_init, /* initialize timer */ #ifdef CONFIG_BOARD_POSTCLK_INIT board_postclk_init,

Dear Simon Glass,
In message 1351813330-23741-4-git-send-email-sjg@chromium.org you wrote:
We want to use the fdt inside board_early_init_f(), so check for its presence earlier in the pre-reloc init sequence.
Signed-off-by: Simon Glass sjg@chromium.org
arch/arm/lib/board.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-)
NAK as is. Please make sure to keep all architectures in sync. The long term goal is still to merge the lib/board.c files into a single, common one.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Nov 3, 2012 at 7:56 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message 1351813330-23741-4-git-send-email-sjg@chromium.org you wrote:
We want to use the fdt inside board_early_init_f(), so check for its presence earlier in the pre-reloc init sequence.
Signed-off-by: Simon Glass sjg@chromium.org
arch/arm/lib/board.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-)
NAK as is. Please make sure to keep all architectures in sync. The long term goal is still to merge the lib/board.c files into a single, common one.
So far ARM and microblaze are the only only ones that use CONFIG_OF_CONTROL. Microblaze does not have the same init loop, and in particular does not have the board_early_init_f() call. So a patch for microblaze would have no meaning.
I have just sent patches to the list to enable CONFIG_OF_CONTROL for x86. I will make the same change to a v2 patch there, and squash it in.
Regarding the generic board series, there was quite a bit of discussion at the time and it ended up being more work than I had time for then. Also I found it very difficult to find all the little errors in board builds when i was making global changes across the tree. Now that I have by builder and a bit more time I plan to take another look at this, probably early next month. When I left it, I had pulled out the common fields in global_data, and got everything building. But it still needs work. I am keen to get this done since it is annoying to have to send 14 patches every time you want to add a new feature!
So we don't have to take this patch, but it would be useful in the meantime.
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 In the future, you're going to get computers as prizes in breakfast cereals. You'll throw them out because your house will be littered with them. - Robert Lucky

This option delays loading of the environment until later, so that only the default environment will be available to U-Boot.
This can address the security risk of untrusted data being used during boot.
When CONFIG_DELAY_ENVIRONMENT is defined, it is convenient to have a run-time way of enabling loadinlg of the environment. Add this to the fdt as /config/delay-environment.
Note: This patch depends on http://patchwork.ozlabs.org/patch/194342/
Signed-off-by: Doug Anderson dianders@chromium.org Signed-off-by: Simon Glass sjg@chromium.org --- README | 9 +++++++++ arch/arm/lib/board.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/README b/README index 22fd6b7..589e22a 100644 --- a/README +++ b/README @@ -2311,6 +2311,15 @@ CBFS (Coreboot Filesystem) support - CONFIG_SYS_VENDOR - CONFIG_SYS_SOC
+ CONFIG_DELAY_ENVIRONMENT + + Normally the environment is loaded when the board is + intialised so that it is available to U-Boot. This inhibits + that so that the environment is not available until + explicitly loaded later by U-Boot code. With CONFIG_OF_CONTROL + this is instead controlled by the value of + /config/load-environment. + - DataFlash Support: CONFIG_HAS_DATAFLASH
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 2ec6a43..d3053d8 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -40,6 +40,7 @@
#include <common.h> #include <command.h> +#include <environment.h> #include <malloc.h> #include <stdio_dev.h> #include <version.h> @@ -469,7 +470,28 @@ static char *failed = "*** failed ***\n"; #endif
/* - ************************************************************************ + * Tell if it's OK to load the environment early in boot. + * + * If CONFIG_OF_CONFIG is defined, we'll check with the FDT to see + * if this is OK (defaulting to saying it's not OK). + * + * NOTE: Loading the environment early can be a bad idea if security is + * important, since no verification is done on the environment. + * + * @return 0 if environment should not be loaded, !=0 if it is ok to load + */ +static int should_load_env(void) +{ +#ifdef CONFIG_OF_CONTROL + return fdtdec_get_config_int(gd->fdt_blob, "load-environment", 0); +#elif defined CONFIG_DELAY_ENVIRONMENT + return 0; +#else + return 1; +#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 @@ -575,7 +597,10 @@ void board_init_r(gd_t *id, ulong dest_addr) #endif
/* initialize environment */ - env_relocate(); + if (should_load_env()) + env_relocate(); + else + set_default_env(NULL);
#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI) arm_pci_init();

Dear Simon Glass,
In message 1351813330-23741-5-git-send-email-sjg@chromium.org you wrote:
This option delays loading of the environment until later, so that only the default environment will be available to U-Boot.
This can address the security risk of untrusted data being used during boot.
When CONFIG_DELAY_ENVIRONMENT is defined, it is convenient to have a run-time way of enabling loadinlg of the environment. Add this to the fdt as /config/delay-environment.
Please explain what exactly this is good for, or which exact "security risks" this is supposed to fix.
As is, I strongly tend to NAK this.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Nov 3, 2012 at 5:30 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message 1351813330-23741-5-git-send-email-sjg@chromium.org you wrote:
This option delays loading of the environment until later, so that only the default environment will be available to U-Boot.
This can address the security risk of untrusted data being used during boot.
When CONFIG_DELAY_ENVIRONMENT is defined, it is convenient to have a run-time way of enabling loadinlg of the environment. Add this to the fdt as /config/delay-environment.
Please explain what exactly this is good for, or which exact "security risks" this is supposed to fix.
Any time you load untrusted data you expose yourself to a bug in the code. The attacker gets to choose the data so can sometimes carefully craft it to exploit a bug. We try to avoid touching user-controlled data during a verified boot unless strictly necessary. Since the default environment is good enough in this case (or you would just change it), this gets around the problem by just not loading the environment.
As is, I strongly tend to NAK this.
Best regards,
Wolfgang Denk
Regards, Simon
-- 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 In the beginning, there was nothing, which exploded. - Terry Pratchett, _Lords and Ladies_

Am Donnerstag, den 01.11.2012, 16:42 -0700 schrieb Simon Glass:
This option delays loading of the environment until later, so that only the default environment will be available to U-Boot.
This can address the security risk of untrusted data being used during boot.
When CONFIG_DELAY_ENVIRONMENT is defined, it is convenient to have a run-time way of enabling loadinlg of the environment. Add this to the fdt as /config/delay-environment.
It's really unfortunate to only realize this after the final release of v2013.01 as I haven't tested the -rc3, but this breaks environment for almost all Tegra boards. I haven't checked all of them, but the ones I looked at have CONFIG_OF_CONTROL defined, but no load-environment node in the FDT.
So they're all going straight into "secure boot" mode, because of the bogus standard value of not allowing env to load, which is probably not what most people want.
Regards, Lucas
[...]
/*
- Tell if it's OK to load the environment early in boot.
- If CONFIG_OF_CONFIG is defined, we'll check with the FDT to see
- if this is OK (defaulting to saying it's not OK).
- NOTE: Loading the environment early can be a bad idea if security is
important, since no verification is done on the environment.
- @return 0 if environment should not be loaded, !=0 if it is ok to load
- */
+static int should_load_env(void) +{ +#ifdef CONFIG_OF_CONTROL
- return fdtdec_get_config_int(gd->fdt_blob, "load-environment", 0);
+#elif defined CONFIG_DELAY_ENVIRONMENT
- return 0;
+#else
- return 1;
+#endif +}
[...]

Hi Lucas,
On Fri, Jan 18, 2013 at 4:06 AM, Lucas Stach dev@lynxeye.de wrote:
Am Donnerstag, den 01.11.2012, 16:42 -0700 schrieb Simon Glass:
This option delays loading of the environment until later, so that only the default environment will be available to U-Boot.
This can address the security risk of untrusted data being used during boot.
When CONFIG_DELAY_ENVIRONMENT is defined, it is convenient to have a run-time way of enabling loadinlg of the environment. Add this to the fdt as /config/delay-environment.
It's really unfortunate to only realize this after the final release of v2013.01 as I haven't tested the -rc3, but this breaks environment for almost all Tegra boards. I haven't checked all of them, but the ones I looked at have CONFIG_OF_CONTROL defined, but no load-environment node in the FDT.
So they're all going straight into "secure boot" mode, because of the bogus standard value of not allowing env to load, which is probably not what most people want.
Hmmm yes I think you are right - the value would be better the other way around. I will create a patch for this and see what people think. I have tended to create my own FDT file but I'm sure many will not.
Regards, Simon
Regards, Lucas
[...]
/*
- Tell if it's OK to load the environment early in boot.
- If CONFIG_OF_CONFIG is defined, we'll check with the FDT to see
- if this is OK (defaulting to saying it's not OK).
- NOTE: Loading the environment early can be a bad idea if security is
important, since no verification is done on the environment.
- @return 0 if environment should not be loaded, !=0 if it is ok to load
- */
+static int should_load_env(void) +{ +#ifdef CONFIG_OF_CONTROL
return fdtdec_get_config_int(gd->fdt_blob, "load-environment", 0);
+#elif defined CONFIG_DELAY_ENVIRONMENT
return 0;
+#else
return 1;
+#endif +}
[...]

This option displays board info after stdio is running, so that it will appear on the LCD. If it is displayed earlier, the board info will appear on the serial console but not on the LCD.
Signed-off-by: Simon Glass sjg@chromium.org
--- README | 9 +++++++++ arch/arm/lib/board.c | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/README b/README index 589e22a..76a8436 100644 --- a/README +++ b/README @@ -3290,6 +3290,15 @@ use the "saveenv" command to store a valid environment. space for already greatly restricted images, including but not limited to NAND_SPL configurations.
+- CONFIG_DISPLAY_BOARDINFO + Display information about the board that U-Boot is running on + when U-Boot starts up. + +- CONFIG_DISPLAY_BOARDINFO_LATE + Similar to the previous option, but display this information + later, once stdio is running and output goes to the LCD, if + present. + Low Level (hardware related) configuration options: ---------------------------------------------------
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index d3053d8..b879507 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -491,6 +491,16 @@ static int should_load_env(void) #endif }
+#if defined(CONFIG_DISPLAY_BOARDINFO_LATE) && defined(CONFIG_OF_CONTROL) +static void display_fdt_model(const void *blob) +{ + const char *model; + + model = (char *)fdt_getprop(blob, 0, "model", NULL); + printf("Model: %s\n", model ? model : "<unknown>"); +} +#endif + /************************************************************************ * * This is the next part if the initialization sequence: we are now @@ -617,6 +627,15 @@ void board_init_r(gd_t *id, ulong dest_addr)
console_init_r(); /* fully init console as a device */
+#ifdef CONFIG_DISPLAY_BOARDINFO_LATE +# ifdef CONFIG_OF_CONTROL + /* Put this here so it appears on the LCD, now it is ready */ + display_fdt_model(gd->fdt_blob); +# else + checkboard(); +# endif +#endif + #if defined(CONFIG_ARCH_MISC_INIT) /* miscellaneous arch dependent initialisations */ arch_misc_init();

Dear Simon Glass,
In message 1351813330-23741-6-git-send-email-sjg@chromium.org you wrote:
This option displays board info after stdio is running, so that it will appear on the LCD. If it is displayed earlier, the board info will appear on the serial console but not on the LCD.
Note that this is intentional! We always want to have the output in the console as soon as possible.
+- CONFIG_DISPLAY_BOARDINFO
Display information about the board that U-Boot is running on
when U-Boot starts up.
Why do we need a config option for this?
This being the default (and I request that this remains so!), you would have to touch _ALL_ existing board config files!
+- CONFIG_DISPLAY_BOARDINFO_LATE
Similar to the previous option, but display this information
later, once stdio is running and output goes to the LCD, if
present.
This makes little sense to me.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Nov 3, 2012 at 5:33 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message 1351813330-23741-6-git-send-email-sjg@chromium.org you wrote:
This option displays board info after stdio is running, so that it will appear on the LCD. If it is displayed earlier, the board info will appear on the serial console but not on the LCD.
Note that this is intentional! We always want to have the output in the console as soon as possible.
(Thanks for your comments on this and other patches, and sorry it had taken a while to get back to this)
The first output on the console is the U-Boot banner. This option does not touch that at all.
+- CONFIG_DISPLAY_BOARDINFO
Display information about the board that U-Boot is running on
when U-Boot starts up.
Why do we need a config option for this?
We already do - I just thought I would document it. Perhaps it should be in a separate commit.
This being the default (and I request that this remains so!), you would have to touch _ALL_ existing board config files!
I don't think it is the default. If I don't define it in my board file, I get no board info.
+- CONFIG_DISPLAY_BOARDINFO_LATE
Similar to the previous option, but display this information
later, once stdio is running and output goes to the LCD, if
present.
This makes little sense to me.
Well, since you asked, here is what we see with and without this option:
1a. Without CONFIG_DISPLAY_BOARDINFO_LATE, on serial:
U-Boot 2011.12-02550-g037e1c5-dirty (Nov 15 2012 - 14:29:42) for SMDK5250
CPU: S5PC520 @ 1700MHz
Board: Google Snow, rev 0 I2C: ready DRAM: 2 GiB Elpida DDR3 @ 800MHz MMC: S5P MSHC0: 0, S5P MSHC1: 1 SF: Detected W25Q32 with page size 4 KiB, total 4 MiB *** Warning - bad CRC, using default environment
In: mkbp-keyb Out: lcd Err: lcd Net: No ethernet found. Hit any key to stop autoboot: 0 SMDK5250 #
1b. Without CONFIG_DISPLAY_BOARDINFO_LATE, on LCD (note machine info is missing):
In: mkbp-keyb Out: lcd Err: lcd Net: No ethernet found. Hit any key to stop autoboot: 0 SMDK5250 #
2a. With CONFIG_DISPLAY_BOARDINFO_LATE, on serial:
U-Boot 2011.12-02550-g037e1c5 (Nov 15 2012 - 14:27:40) for SMDK5250
CPU: S5PC520 @ 1700MHz I2C: ready DRAM: 2 GiB Elpida DDR3 @ 800MHz MMC: S5P MSHC0: 0, S5P MSHC1: 1 SF: Detected W25Q32 with page size 4 KiB, total 4 MiB *** Warning - bad CRC, using default environment
Model: Google Snow In: mkbp-keyb Out: lcd Err: lcd Net: No ethernet found. Hit any key to stop autoboot: 0 SMDK5250 #
2b. With CONFIG_DISPLAY_BOARDINFO_LATE, on LCD (note machine info is present):
Model: Google Snow In: mkbp-keyb Out: lcd Err: lcd Net: No ethernet found. Hit any key to stop autoboot: 0 SMDK5250 #
Since the LCD is all that a typical user sees, it is useful to display the model there.
We may be able to rearrange things some other way one day, but at present this seems like a convenient way of getting the required behaviour.
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 Each kiss is as the first. -- Miramanee, Kirk's wife, "The Paradise Syndrome", stardate 4842.6

Some boards want to report more than just memory size. For example, it might be useful to display the memory type (DDR2, DDR3) or manufacturer.
Add a weak function to support this requirement.
Any example of the DRAM: output is below, just for illustration:
U-Boot 2011.12-02470-gd64a0f8-dirty (Sep 14 2012 - 10:46:39) for SMDK5250
CPU: S5PC520 @ 1700MHz I2C: ready DRAM: 2 GiB Samsung DDR3 @ 800MHz MMC: S5P MSHC0: 0, S5P MSHC1: 1 Using default environment
Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/lib/board.c | 12 ++++++++++-- include/common.h | 9 +++++++++ 2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index b879507..d420307 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -133,6 +133,15 @@ static int display_banner(void) return (0); }
+inline void __board_show_dram(ulong size) +{ + puts("DRAM: "); + print_size(size, "\n"); +} + +void board_show_dram(ulong size) + __attribute__((weak, alias("__board_show_dram"))); + /* * WARNING: this code looks "cleaner" than the PowerPC version, but * has the disadvantage that you either get nothing, or everything. @@ -157,8 +166,7 @@ static int display_dram_config(void) for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) size += gd->bd->bi_dram[i].size;
- puts("DRAM: "); - print_size(size, "\n"); + board_show_dram(size); #endif
return (0); diff --git a/include/common.h b/include/common.h index b23e90b..6270b44 100644 --- a/include/common.h +++ b/include/common.h @@ -311,6 +311,15 @@ int mac_read_from_eeprom(void); extern u8 _binary_dt_dtb_start[]; /* embedded device tree blob */ int set_cpu_clk_info(void);
+/** + * Show the DRAM size in a board-specific way + * + * This is used by boards to display DRAM information in their own way. + * + * @param size Size of DRAM (which should be displayed along with other info) + */ +void board_show_dram(ulong size); + /* common/flash.c */ void flash_perror (int);

Dear Simon Glass,
In message 1351813330-23741-7-git-send-email-sjg@chromium.org you wrote:
Some boards want to report more than just memory size. For example, it might be useful to display the memory type (DDR2, DDR3) or manufacturer.
Add a weak function to support this requirement.
Any example of the DRAM: output is below, just for illustration:
U-Boot 2011.12-02470-gd64a0f8-dirty (Sep 14 2012 - 10:46:39) for SMDK5250
CPU: S5PC520 @ 1700MHz I2C: ready DRAM: 2 GiB Samsung DDR3 @ 800MHz MMC: S5P MSHC0: 0, S5P MSHC1: 1 Using default environment
NAK.
Such information does not belong into the standard boot messages. These should containonly the necessary information to see that U-Boot is coming up correctly and give indication where it might be hanging if it does.
All other information should be printed by commands that may be called by users who are actually interested in such information. You may even add such commands to your "preboot" settings, but please make sure that users not interested in such stuff can change this and get only minimal output (as may be needed for minimal boot times).
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Nov 3, 2012 at 7:54 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message 1351813330-23741-7-git-send-email-sjg@chromium.org you wrote:
Some boards want to report more than just memory size. For example, it might be useful to display the memory type (DDR2, DDR3) or manufacturer.
Add a weak function to support this requirement.
Any example of the DRAM: output is below, just for illustration:
U-Boot 2011.12-02470-gd64a0f8-dirty (Sep 14 2012 - 10:46:39) for SMDK5250
CPU: S5PC520 @ 1700MHz I2C: ready DRAM: 2 GiB Samsung DDR3 @ 800MHz MMC: S5P MSHC0: 0, S5P MSHC1: 1 Using default environment
NAK.
Such information does not belong into the standard boot messages. These should containonly the necessary information to see that U-Boot is coming up correctly and give indication where it might be hanging if it does.
All other information should be printed by commands that may be called by users who are actually interested in such information. You may even add such commands to your "preboot" settings, but please make sure that users not interested in such stuff can change this and get only minimal output (as may be needed for minimal boot times).
A key reason for not coming up correctly is the memory being configured incorrectly - e.g. timings or type incorrect.
I will see if I can add a command for this.
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 If a person (a) is poorly, (b) receives treatment intended to make him better, and (c) gets better, then no power of reasoning known to medical science can convince him that it may not have been the treatment that restored his health.
- Sir Peter Medawar, The Art of the Soluble

From: Tom Wai-Hong Tam waihong@chromium.org
SPL u-boot may call do_reset() which depends on interrupts.o and reset.o. So make them also appear in SPL.
Signed-off-by: Tom Wai-Hong Tam waihong@chromium.org Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/lib/Makefile | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 3422ac1..2fbdc07 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -40,14 +40,15 @@ ifndef CONFIG_SPL_BUILD COBJS-y += board.o COBJS-y += bootm.o COBJS-$(CONFIG_SYS_L2_PL310) += cache-pl310.o -COBJS-y += interrupts.o -COBJS-y += reset.o SOBJS-$(CONFIG_USE_ARCH_MEMSET) += memset.o SOBJS-$(CONFIG_USE_ARCH_MEMCPY) += memcpy.o else COBJS-$(CONFIG_SPL_FRAMEWORK) += spl.o endif
+COBJS-y += interrupts.o +COBJS-y += reset.o + COBJS-y += cache.o COBJS-y += cache-cp15.o

The timer may be inited in arch_cpu_init() so it is not safe to make a bootstage mark before this is called. Arrange the code to fix this.
We now get a correct time for board_init_f:
Timer summary in microseconds: Mark Elapsed Stage 0 0 reset 100,000 100,000 spl_start 848,530 748,530 board_init_f 907,301 58,771 board_init_r 910,478 3,177 board_init
Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/lib/board.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index d420307..ec3739f 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -233,8 +233,17 @@ int __arch_cpu_init(void) int arch_cpu_init(void) __attribute__((weak, alias("__arch_cpu_init")));
+/* Record the board_init_f() bootstage (after arch_cpu_init()) */ +static int mark_bootstage(void) +{ + bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f"); + + return 0; +} + init_fnc_t *init_sequence[] = { arch_cpu_init, /* basic arch cpu dependent setup */ + mark_bootstage, #ifdef CONFIG_OF_CONTROL fdtdec_check_fdt, #endif @@ -278,8 +287,6 @@ void board_init_f(ulong bootflag) void *new_fdt = NULL; size_t fdt_size = 0;
- bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f"); - /* 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 */

Dear Simon Glass,
In message 1351813330-23741-9-git-send-email-sjg@chromium.org you wrote:
The timer may be inited in arch_cpu_init() so it is not safe to make a bootstage mark before this is called. Arrange the code to fix this.
We now get a correct time for board_init_f:
Timer summary in microseconds: Mark Elapsed Stage 0 0 reset 100,000 100,000 spl_start 848,530 748,530 board_init_f 907,301 58,771 board_init_r 910,478 3,177 board_init
Signed-off-by: Simon Glass sjg@chromium.org
arch/arm/lib/board.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-)
NAK as is. Please make sure to keep all arhcitectures in sync. The long term goal iss till to merge the lib/board.c files into a single, common one.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Nov 3, 2012 at 7:55 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message 1351813330-23741-9-git-send-email-sjg@chromium.org you wrote:
The timer may be inited in arch_cpu_init() so it is not safe to make a bootstage mark before this is called. Arrange the code to fix this.
We now get a correct time for board_init_f:
Timer summary in microseconds: Mark Elapsed Stage 0 0 reset 100,000 100,000 spl_start 848,530 748,530 board_init_f 907,301 58,771 board_init_r 910,478 3,177 board_init
Signed-off-by: Simon Glass sjg@chromium.org
arch/arm/lib/board.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-)
NAK as is. Please make sure to keep all arhcitectures in sync. The long term goal iss till to merge the lib/board.c files into a single, common one.
See my notes on the other patch, most of which apply here.
http://patchwork.ozlabs.org/patch/196419/
I don't believe this affects other architectures, but it is a problem on at least exynos 5.
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 universe contains any amount of horrible ways to be woken up, such as the noise of the mob breaking down the front door, the scream of fire engines, or the realization that today is the Monday which on Friday night was a comfortably long way off. - Terry Pratchett, _Moving Pictures_

Dear Simon,
In message CAPnjgZ0D4g4bK70VooK3SYkMzOwLSyPXdjE2yCn3gvJ1jAv6EQ@mail.gmail.com you wrote:
NAK as is. Please make sure to keep all arhcitectures in sync. The long term goal iss till to merge the lib/board.c files into a single, common one.
See my notes on the other patch, most of which apply here.
http://patchwork.ozlabs.org/patch/196419/
I don't believe this affects other architectures, but it is a problem on at least exynos 5.
Well, but if you just compare arch/arm/lib/board.c and arch/powerpc/lib/board.c, we are heading into pretty much deviation directions. I'd like to stop that.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Wed, Nov 7, 2012 at 5:18 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon,
In message CAPnjgZ0D4g4bK70VooK3SYkMzOwLSyPXdjE2yCn3gvJ1jAv6EQ@mail.gmail.com you wrote:
NAK as is. Please make sure to keep all arhcitectures in sync. The long term goal iss till to merge the lib/board.c files into a single, common one.
See my notes on the other patch, most of which apply here.
http://patchwork.ozlabs.org/patch/196419/
I don't believe this affects other architectures, but it is a problem on at least exynos 5.
Well, but if you just compare arch/arm/lib/board.c and arch/powerpc/lib/board.c, we are heading into pretty much deviation directions. I'd like to stop that.
Well powerpc doesn't have specific bootstage markers at present (although it does use boot progress). I hope that the generic board series will solve this problem in general, but in the meantime this is a real problem, and only in ARM.
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 It is impractical for the standard to attempt to constrain the behavior of code that does not obey the constraints of the standard. - Doug Gwyn

From: Taylor Hutt thutt@chromium.org
The two modified lines were indented with spaces. They are now indented with tabs.
Signed-off-by: Taylor Hutt thutt@chromium.org Signed-off-by: Simon Glass sjg@chromium.org --- arch/arm/lib/board.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index ec3739f..288ce45 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -612,8 +612,8 @@ void board_init_r(gd_t *id, ulong dest_addr) #endif
#ifdef CONFIG_GENERIC_MMC - puts("MMC: "); - mmc_initialize(gd->bd); + puts("MMC: "); + mmc_initialize(gd->bd); #endif
#ifdef CONFIG_HAS_DATAFLASH

Dear Simon Glass,
It is good to have these functions written in C instead of assembler, but with -O0 the cache_disable() function doesn't return. Rather than revert to assembler, this fix just forces this to be built with -O2.
Signed-off-by: Simon Glass sjg@chromium.org
arch/arm/lib/cache-cp15.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c index 939de10..8f8385d 100644 --- a/arch/arm/lib/cache-cp15.c +++ b/arch/arm/lib/cache-cp15.c @@ -110,6 +110,16 @@ static void cache_enable(uint32_t cache_bit) set_cr(reg | cache_bit); }
+/*
- Big hack warning!
- Devs like to compile with -O0 to get a nice debugging illusion. But
this + * function does not survive that since -O0 causes the compiler to read the + * PC back from the stack after the dcache flush. Might it be possible to fix + * this by flushing the write buffer?
- */
+static void cache_disable(uint32_t cache_bit) __attribute__ ((optimize(2))); + /* cache_bit must be either CR_I or CR_C */ static void cache_disable(uint32_t cache_bit) {
Uh, are you sure this is right ?
Best regards, Marek Vasut

Dear Simon Glass,
In message 1351813330-23741-1-git-send-email-sjg@chromium.org you wrote:
It is good to have these functions written in C instead of assembler, but with -O0 the cache_disable() function doesn't return. Rather than revert to assembler, this fix just forces this to be built with -O2.
NAK.
This is vodoo programming to fix a problem which is obviously not correctly understood (and fixed), so the real cause remains unfixed.
+/*
- Big hack warning!
- Devs like to compile with -O0 to get a nice debugging illusion. But this
We don't use -O0 normally, and actually there are more places in the code that are likely to cause problems or to actually break when using -O0.
- function does not survive that since -O0 causes the compiler to read the
- PC back from the stack after the dcache flush. Might it be possible to fix
- this by flushing the write buffer?
- */
"compiler to read the PC back from the stack after the dcache flush" - can you please explain what exactly this means, and which exact problem it causes?
+static void cache_disable(uint32_t cache_bit) __attribute__ ((optimize(2)));
Sorry, I will not accept this.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Nov 3, 2012 at 5:29 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message 1351813330-23741-1-git-send-email-sjg@chromium.org you wrote:
It is good to have these functions written in C instead of assembler, but with -O0 the cache_disable() function doesn't return. Rather than revert to assembler, this fix just forces this to be built with -O2.
NAK.
This is vodoo programming to fix a problem which is obviously not correctly understood (and fixed), so the real cause remains unfixed.
+/*
- Big hack warning!
- Devs like to compile with -O0 to get a nice debugging illusion. But this
We don't use -O0 normally, and actually there are more places in the code that are likely to cause problems or to actually break when using -O0.
- function does not survive that since -O0 causes the compiler to read the
- PC back from the stack after the dcache flush. Might it be possible to fix
- this by flushing the write buffer?
- */
"compiler to read the PC back from the stack after the dcache flush" - can you please explain what exactly this means, and which exact problem it causes?
This is the code without the patch (armv7) using -O0:
00000248 <cache_disable>: 248: e92d4810 push {r4, fp, lr} 24c: e28db008 add fp, sp, #8 250: e24dd01c sub sp, sp, #28 254: e50b0020 str r0, [fp, #-32] 258: ee114f10 mrc 15, 0, r4, cr1, cr0, {0} 25c: e50b4014 str r4, [fp, #-20] 260: e51b3014 ldr r3, [fp, #-20] 264: e50b3010 str r3, [fp, #-16] 268: ebffff69 bl 14 <cp_delay> 26c: e51b3020 ldr r3, [fp, #-32] 270: e3530004 cmp r3, #4 274: 1a000007 bne 298 <cache_disable+0x50> 278: e51b3010 ldr r3, [fp, #-16] 27c: e2033004 and r3, r3, #4 280: e3530000 cmp r3, #0 284: 0a00000b beq 2b8 <cache_disable+0x70> 288: e51b3020 ldr r3, [fp, #-32] 28c: e3833001 orr r3, r3, #1 290: e50b3020 str r3, [fp, #-32] 294: ebfffffe bl 0 <flush_dcache_all> 298: e51b3020 ldr r3, [fp, #-32] ^^^^^^^^^^^^^
29c: e1e02003 mvn r2, r3 2a0: e51b3010 ldr r3, [fp, #-16] 2a4: e0023003 and r3, r2, r3 2a8: e50b3018 str r3, [fp, #-24] 2ac: e51b3018 ldr r3, [fp, #-24] 2b0: ee013f10 mcr 15, 0, r3, cr1, cr0, {0} 2b4: ea000000 b 2bc <cache_disable+0x74> 2b8: e1a00000 nop ; (mov r0, r0) 2bc: e24bd008 sub sp, fp, #8 2c0: e8bd8810 pop {r4, fp, pc}
this is the code with the patch:
00000124 <dcache_disable>: 124: e92d4010 push {r4, lr} 128: ebffffb4 bl 0 <cp_delay> 12c: ee114f10 mrc 15, 0, r4, cr1, cr0, {0} 130: e3140004 tst r4, #4 134: 08bd8010 popeq {r4, pc} 138: ebfffffe bl 0 <flush_dcache_all> 13c: e3c44005 bic r4, r4, #5 140: ee014f10 mcr 15, 0, r4, cr1, cr0, {0} 144: e8bd8010 pop {r4, pc}
I have marked with ^^^^^^^^^^ the line that I think it dies. I did not spent a lot of time looking at it - just found the problem with an ICE and then tried to fix it. I suspect it can be fixed with some sort of dsb() in flush_dcache_all(), but I am not sure.
Unfortunately things have moved on and I can't easily test this (now using Thumb2 where -O0 isn't quite so extreme).
+static void cache_disable(uint32_t cache_bit) __attribute__ ((optimize(2)));
Sorry, I will not accept this.
OK. If I hit it again next time I will try a bit harder to root cause it.
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 backups: always in season, never out of style.

Dear Simon,
In message CAPnjgZ38TZr2ztdq5D8fNfgCz9a+-vGJFv0saezJWiQBHh-FwA@mail.gmail.com you wrote:
"compiler to read the PC back from the stack after the dcache flush" - can you please explain what exactly this means, and which exact problem it causes?
This is the code without the patch (armv7) using -O0:
00000248 <cache_disable>: 248: e92d4810 push {r4, fp, lr} 24c: e28db008 add fp, sp, #8 250: e24dd01c sub sp, sp, #28 254: e50b0020 str r0, [fp, #-32] 258: ee114f10 mrc 15, 0, r4, cr1, cr0, {0} 25c: e50b4014 str r4, [fp, #-20] 260: e51b3014 ldr r3, [fp, #-20] 264: e50b3010 str r3, [fp, #-16] 268: ebffff69 bl 14 <cp_delay> 26c: e51b3020 ldr r3, [fp, #-32] 270: e3530004 cmp r3, #4 274: 1a000007 bne 298 <cache_disable+0x50> 278: e51b3010 ldr r3, [fp, #-16] 27c: e2033004 and r3, r3, #4 280: e3530000 cmp r3, #0 284: 0a00000b beq 2b8 <cache_disable+0x70> 288: e51b3020 ldr r3, [fp, #-32] 28c: e3833001 orr r3, r3, #1 290: e50b3020 str r3, [fp, #-32] 294: ebfffffe bl 0 <flush_dcache_all> 298: e51b3020 ldr r3, [fp, #-32] ^^^^^^^^^^^^^
29c: e1e02003 mvn r2, r3 2a0: e51b3010 ldr r3, [fp, #-16] 2a4: e0023003 and r3, r2, r3 2a8: e50b3018 str r3, [fp, #-24] 2ac: e51b3018 ldr r3, [fp, #-24] 2b0: ee013f10 mcr 15, 0, r3, cr1, cr0, {0} 2b4: ea000000 b 2bc <cache_disable+0x74> 2b8: e1a00000 nop ; (mov r0, r0) 2bc: e24bd008 sub sp, fp, #8 2c0: e8bd8810 pop {r4, fp, pc}
this is the code with the patch:
00000124 <dcache_disable>: 124: e92d4010 push {r4, lr} 128: ebffffb4 bl 0 <cp_delay> 12c: ee114f10 mrc 15, 0, r4, cr1, cr0, {0} 130: e3140004 tst r4, #4 134: 08bd8010 popeq {r4, pc} 138: ebfffffe bl 0 <flush_dcache_all> 13c: e3c44005 bic r4, r4, #5 140: ee014f10 mcr 15, 0, r4, cr1, cr0, {0} 144: e8bd8010 pop {r4, pc}
I have marked with ^^^^^^^^^^ the line that I think it dies. I did not spent a lot of time looking at it - just found the problem with an ICE and then tried to fix it. I suspect it can be fixed with some sort of dsb() in flush_dcache_all(), but I am not sure.
The code is actually pretty much different - note that the version above contains calls to cache_disable() which are not visible in the code below.
But then - the insn you mark is restoring r3 from the stack, after iut was stored there right before calling flush_dcache_all(). Why should this cause problems? And in which way is this "read[ing] the PC back from the stack" ? r3 is not the PC, right?
OK. If I hit it again next time I will try a bit harder to root cause it.
Thanks, and sorry for insisting on a real explanation for obscure problems.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Wed, Nov 7, 2012 at 4:55 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon,
In message CAPnjgZ38TZr2ztdq5D8fNfgCz9a+-vGJFv0saezJWiQBHh-FwA@mail.gmail.com you wrote:
"compiler to read the PC back from the stack after the dcache flush" - can you please explain what exactly this means, and which exact problem it causes?
This is the code without the patch (armv7) using -O0:
00000248 <cache_disable>: 248: e92d4810 push {r4, fp, lr} 24c: e28db008 add fp, sp, #8 250: e24dd01c sub sp, sp, #28 254: e50b0020 str r0, [fp, #-32] 258: ee114f10 mrc 15, 0, r4, cr1, cr0, {0} 25c: e50b4014 str r4, [fp, #-20] 260: e51b3014 ldr r3, [fp, #-20] 264: e50b3010 str r3, [fp, #-16] 268: ebffff69 bl 14 <cp_delay> 26c: e51b3020 ldr r3, [fp, #-32] 270: e3530004 cmp r3, #4 274: 1a000007 bne 298 <cache_disable+0x50> 278: e51b3010 ldr r3, [fp, #-16] 27c: e2033004 and r3, r3, #4 280: e3530000 cmp r3, #0 284: 0a00000b beq 2b8 <cache_disable+0x70> 288: e51b3020 ldr r3, [fp, #-32] 28c: e3833001 orr r3, r3, #1 290: e50b3020 str r3, [fp, #-32] 294: ebfffffe bl 0 <flush_dcache_all> 298: e51b3020 ldr r3, [fp, #-32] ^^^^^^^^^^^^^
29c: e1e02003 mvn r2, r3 2a0: e51b3010 ldr r3, [fp, #-16] 2a4: e0023003 and r3, r2, r3 2a8: e50b3018 str r3, [fp, #-24] 2ac: e51b3018 ldr r3, [fp, #-24] 2b0: ee013f10 mcr 15, 0, r3, cr1, cr0, {0} 2b4: ea000000 b 2bc <cache_disable+0x74> 2b8: e1a00000 nop ; (mov r0, r0) 2bc: e24bd008 sub sp, fp, #8 2c0: e8bd8810 pop {r4, fp, pc}
this is the code with the patch:
00000124 <dcache_disable>: 124: e92d4010 push {r4, lr} 128: ebffffb4 bl 0 <cp_delay> 12c: ee114f10 mrc 15, 0, r4, cr1, cr0, {0} 130: e3140004 tst r4, #4 134: 08bd8010 popeq {r4, pc} 138: ebfffffe bl 0 <flush_dcache_all> 13c: e3c44005 bic r4, r4, #5 140: ee014f10 mcr 15, 0, r4, cr1, cr0, {0} 144: e8bd8010 pop {r4, pc}
I have marked with ^^^^^^^^^^ the line that I think it dies. I did not spent a lot of time looking at it - just found the problem with an ICE and then tried to fix it. I suspect it can be fixed with some sort of dsb() in flush_dcache_all(), but I am not sure.
The code is actually pretty much different - note that the version above contains calls to cache_disable() which are not visible in the code below.
But then - the insn you mark is restoring r3 from the stack, after iut was stored there right before calling flush_dcache_all(). Why should this cause problems? And in which way is this "read[ing] the PC back from the stack" ? r3 is not the PC, right?
I wish I could easily repeat this, but I am not set up for it now, and the code bases have moved on. I recall that the PC value read from the stack (in one of the pop operations0 was wrong.
OK. If I hit it again next time I will try a bit harder to root cause it.
Thanks, and sorry for insisting on a real explanation for obscure problems.
Well fair enough I think. Maybe someone else will hit it and this thread will be useful for them to root cause. I find the need for -O0 is much reduced now that the tools are better.
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 Teenagers are people who express a burning desire to be different by dressing exactly alike. There are some strings. They're just not attached.
participants (4)
-
Lucas Stach
-
Marek Vasut
-
Simon Glass
-
Wolfgang Denk