Patchwork [U-Boot,v6,RFC] early_malloc for DM added.

login
register
mail settings
Submitter Tomas Hlavacek
Date Sept. 22, 2012, 10:09 p.m.
Message ID <1348351758-7434-1-git-send-email-tmshlvck@gmail.com>
Download mbox | patch
Permalink /patch/186171/
State RFC
Headers show

Comments

Tomas Hlavacek - Sept. 22, 2012, 10:09 p.m.
early_malloc for DM with support for more heaps and lightweight
first heap in the same memory as an early stack.

Adaptation layer for seamless calling of early_malloc or dlmalloc from
DM based on init stage added (dmmalloc() and related functions).

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---

Changelog since v5:
dmmalloc() and all dm* functions has been moved to header, made static
inline and preprocessor-dependent blocks are reworked.
early_malloc_active() corrected and made not static.
s/CONFIG_SYS_DM/CONFIG_DM/ applied.

 arch/arm/include/asm/global_data.h        |    3 +
 arch/arm/lib/board.c                      |    8 +++
 arch/avr32/include/asm/global_data.h      |    3 +
 arch/avr32/lib/board.c                    |    9 +++
 arch/blackfin/include/asm/global_data.h   |    3 +
 arch/blackfin/lib/board.c                 |    8 +++
 arch/m68k/include/asm/global_data.h       |    3 +
 arch/m68k/lib/board.c                     |    8 +++
 arch/microblaze/include/asm/global_data.h |    3 +
 arch/microblaze/lib/board.c               |    9 +++
 arch/mips/include/asm/global_data.h       |    3 +
 arch/mips/lib/board.c                     |    8 +++
 arch/nds32/include/asm/global_data.h      |    3 +
 arch/nds32/lib/board.c                    |    8 +++
 arch/nios2/include/asm/global_data.h      |    3 +
 arch/nios2/lib/board.c                    |    8 +++
 arch/openrisc/include/asm/global_data.h   |    3 +
 arch/openrisc/lib/board.c                 |    8 +++
 arch/powerpc/include/asm/global_data.h    |    3 +
 arch/powerpc/lib/board.c                  |    8 +++
 arch/sandbox/include/asm/global_data.h    |    3 +
 arch/sandbox/lib/board.c                  |    8 +++
 arch/sh/include/asm/global_data.h         |    3 +
 arch/sh/lib/board.c                       |    8 +++
 arch/sparc/include/asm/global_data.h      |    3 +
 arch/sparc/lib/board.c                    |    8 +++
 arch/x86/include/asm/global_data.h        |    3 +
 arch/x86/lib/board.c                      |   18 ++++++
 common/Makefile                           |    1 +
 common/dmmalloc.c                         |   93 +++++++++++++++++++++++++++++
 include/dmmalloc.h                        |   89 +++++++++++++++++++++++++++
 31 files changed, 349 insertions(+)
 create mode 100644 common/dmmalloc.c
 create mode 100644 include/dmmalloc.h
Graeme Russ - Sept. 23, 2012, 1:06 p.m.
On Sep 23, 2012 8:09 AM, "Tomas Hlavacek" <tmshlvck@gmail.com> wrote:
>
> early_malloc for DM with support for more heaps and lightweight
> first heap in the same memory as an early stack.
>
> Adaptation layer for seamless calling of early_malloc or dlmalloc from
> DM based on init stage added (dmmalloc() and related functions).
>
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---

[snip]

> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +__weak struct early_heap_header *early_brk(size_t size)
> +{
> +       struct early_heap_header *h =
> +               (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
> +       struct early_heap_header *ehp = gd->early_heap_first;
> +
> +       while (ehp != NULL) {
> +               if (ehp == h)
> +                       return NULL;
> +
> +               ehp = ehp->next_early_heap;
> +       }

if (g->early_heap_first == NULL)
    h = CONFIF_SYS_EARLY_HEAP_ADDR);
else
    return NULL;

> +
> +       h->free_space_pointer = (void *)(roundup(
> +                               (phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
> +                               sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t)));
> +       h->free_bytes = size - roundup(sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t));
> +       h->next_early_heap = NULL;
> +
> +       return h;
> +}

Regards,

Graeme
Tomas Hlavacek - Sept. 23, 2012, 3:30 p.m.
Hello!

On Sun, Sep 23, 2012 at 3:06 PM, Graeme Russ <graeme.russ@gmail.com> wrote:
>
> On Sep 23, 2012 8:09 AM, "Tomas Hlavacek" <tmshlvck@gmail.com> wrote:
>>
>> early_malloc for DM with support for more heaps and lightweight
>> first heap in the same memory as an early stack.
>>
>> Adaptation layer for seamless calling of early_malloc or dlmalloc from
>> DM based on init stage added (dmmalloc() and related functions).
>>
>> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
>> ---
>
> [snip]
>
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +__weak struct early_heap_header *early_brk(size_t size)
>> +{
>> +       struct early_heap_header *h =
>> +               (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
>> +       struct early_heap_header *ehp = gd->early_heap_first;
>> +
>> +       while (ehp != NULL) {
>> +               if (ehp == h)
>> +                       return NULL;
>> +
>> +               ehp = ehp->next_early_heap;
>> +       }
>
> if (g->early_heap_first == NULL)
>     h = CONFIF_SYS_EARLY_HEAP_ADDR);
> else
>     return NULL;

Yes, I was too paranoid. What about:

if (g->early_heap_first != NULL)
                return NULL;

>
>> +
>> +       h->free_space_pointer = (void *)(roundup(
>> +                               (phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
>> +                               sizeof(struct early_heap_header),
>> +                               sizeof(phys_addr_t)));
>> +       h->free_bytes = size - roundup(sizeof(struct early_heap_header),
>> +                               sizeof(phys_addr_t));
>> +       h->next_early_heap = NULL;
>> +
>> +       return h;
>> +}
>

Tomas

Patch

diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index f8088fe..ef727b0 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -82,6 +82,9 @@  typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index f1951e8..f73d8b2 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -53,6 +53,10 @@ 
 #include <post.h>
 #include <logbuff.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
 #endif
@@ -281,6 +285,10 @@  void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = _bss_end_ofs;
 #ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index 7878bb1..0654a61 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -48,6 +48,9 @@  typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index d7a64b4..f1bd946 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -42,6 +42,11 @@ 
 #ifdef CONFIG_GENERIC_ATMEL_MCI
 #include <mmc.h>
 #endif
+
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 unsigned long monitor_flash_len;
@@ -161,6 +166,10 @@  void board_init_f(ulong board_type)
 	memset(&gd_data, 0, sizeof(gd_data));
 	gd = &gd_data;
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	/* Perform initialization sequence */
 	board_early_init_f();
 	cpu_init();
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index 290a9e7..2ae395c 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -57,6 +57,9 @@  typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index c380d27..96b7d76 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -37,6 +37,10 @@ 
 int post_flag;
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 __attribute__((always_inline))
@@ -267,6 +271,10 @@  void board_init_f(ulong bootflag)
 	watchdog_init();
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #ifdef DEBUG
 	if (GENERATED_GBL_DATA_SIZE < sizeof(*gd))
 		hang();
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index cd55b83..bd30435 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -66,6 +66,9 @@  typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 65a8595..1b9312c 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -69,6 +69,10 @@ 
 
 #include <nand.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static char *failed = "*** failed ***\n";
@@ -227,6 +231,10 @@  board_init_f (ulong bootflag)
 	/* Clear initial global data */
 	memset ((void *) gd, 0, sizeof (gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0) {
 			hang ();
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index de3b8db..6f4066d 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -46,6 +46,9 @@  typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 674b573..eeb8441 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -37,6 +37,10 @@ 
 #include <asm/microblaze_intc.h>
 #include <fdtdec.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -81,6 +85,11 @@  void board_init_f(ulong not_used)
 	asm ("nop");	/* FIXME gd is not initialize - wait */
 	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index 6e2cdc7..ac24e3f 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -59,6 +59,9 @@  typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
index 62d47a8..4657046 100644
--- a/arch/mips/lib/board.c
+++ b/arch/mips/lib/board.c
@@ -36,6 +36,10 @@ 
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -153,6 +157,10 @@  void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index 94bd4c2..d0e2606 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -63,6 +63,9 @@  typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 2164a50..97193b0 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -37,6 +37,10 @@ 
 #include <onenand_uboot.h>
 #include <mmc.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -192,6 +196,10 @@  void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = (unsigned int)(&__bss_end__) - (unsigned int)(&_start);
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 3b0d9e6..44373f4 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -42,6 +42,9 @@  typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index 1e495d4..866dc12 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -40,6 +40,10 @@ 
 #include <nand.h>	/* cannot even include nand.h if it isnt configured */
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -95,6 +99,10 @@  void board_init (void)
 	/* compiler optimization barrier needed for GCC >= 3.4 */
 	__asm__ __volatile__("": : :"memory");
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = &bd_data;
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 6a0c0cc..ec2220a 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -44,6 +44,9 @@  typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 85aa189..f1199d6 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -44,6 +44,10 @@ 
 #include <timestamp.h>
 #include <version.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -86,6 +90,10 @@  void board_init(void)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 5a5877f..38b63f9 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -182,6 +182,9 @@  typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index fea310e..39af242 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -87,6 +87,10 @@ 
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_SYS_UPDATE_FLASH_SIZE
 extern int update_flash_size(int flash_size);
 #endif
@@ -389,6 +393,10 @@  void board_init_f(ulong bootflag)
 	memset((void *) gd, 0, sizeof(gd_t));
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
 		if ((*init_fnc_ptr) () != 0)
 			hang();
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 581fd2f..00c7c10 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -46,6 +46,9 @@  typedef	struct 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. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index c173bf9..d384481 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -47,6 +47,10 @@ 
 
 #include <os.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static gd_t gd_mem;
@@ -157,6 +161,10 @@  void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #if defined(CONFIG_OF_EMBED)
 	/* Get a pointer to the FDT */
 	gd->fdt_blob = _binary_dt_dtb_start;
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 6e534ad..441fecd 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -42,6 +42,9 @@  typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
index 34d7881..eb04ed2 100644
--- a/arch/sh/lib/board.c
+++ b/arch/sh/lib/board.c
@@ -32,6 +32,10 @@ 
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 extern int cpu_init(void);
@@ -150,6 +154,10 @@  void sh_generic_init(void)
 
 	memset(gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
 
 	gd->bd = (bd_t *)(gd + 1);	/* At end of global data */
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index 93d3cc0..537e09a 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -74,6 +74,9 @@  typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 6f33666..2ced0a7 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -53,6 +53,10 @@ 
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Debug options
@@ -178,6 +182,10 @@  void board_init_f(ulong bootflag)
 	/* Clear initial global data */
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 6d29c0b..920a805 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -57,6 +57,9 @@  typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index 90cf7fc..a670f9e 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -40,6 +40,10 @@ 
 #include <asm/init_helpers.h>
 #include <asm/init_wrappers.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 /*
  * Breath some life into the board...
  *
@@ -85,6 +89,17 @@ 
 typedef int (init_fnc_t) (void);
 
 /*
+ * Initialize early heap (when enabled by config).
+ */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+static void early_malloc_init(void)
+{
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+
+/*
  * init_sequence_f is the list of init functions which are run when U-Boot
  * is executing from Flash with a limited 'C' environment. The following
  * limitations must be considered when implementing an '_f' function:
@@ -99,6 +114,9 @@  init_fnc_t *init_sequence_f[] = {
 	cpu_init_f,
 	board_early_init_f,
 	env_init,
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	early_malloc_init,
+#endif /* CONFIG_SYS_EARLY_MALLOC */
 	init_baudrate_f,
 	serial_init,
 	console_init_f,
diff --git a/common/Makefile b/common/Makefile
index 22e8a6f..5862d34 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -201,6 +201,7 @@  COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-$(CONFIG_DM) += dmmalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/dmmalloc.c b/common/dmmalloc.c
new file mode 100644
index 0000000..3db0d7b
--- /dev/null
+++ b/common/dmmalloc.c
@@ -0,0 +1,93 @@ 
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck@gmail.com)
+ *
+ * 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> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <dmmalloc.h>
+#include <malloc.h>
+
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+__weak struct early_heap_header *early_brk(size_t size)
+{
+	struct early_heap_header *h =
+		(struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
+	struct early_heap_header *ehp = gd->early_heap_first;
+
+	while (ehp != NULL) {
+		if (ehp == h)
+			return NULL;
+
+		ehp = ehp->next_early_heap;
+	}
+
+	h->free_space_pointer = (void *)(roundup(
+				(phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
+				sizeof(struct early_heap_header),
+				sizeof(phys_addr_t)));
+	h->free_bytes = size - roundup(sizeof(struct early_heap_header),
+				sizeof(phys_addr_t));
+	h->next_early_heap = NULL;
+
+	return h;
+}
+
+void *early_malloc(size_t size)
+{
+	phys_addr_t addr;
+	struct early_heap_header *h;
+
+	size = roundup(size, sizeof(phys_addr_t));
+
+	h = gd->early_heap_first;
+	while ((h->free_bytes < size) && (h->next_early_heap != NULL))
+		h = h->next_early_heap;
+
+	if (h->free_bytes < size) {
+		h->next_early_heap = early_brk(size);
+		if (h->next_early_heap == NULL)
+			debug("EH overflow. Can not early_brk. required %d B.",
+			size);
+		return NULL;
+	}
+
+	addr = (phys_addr_t)h->free_space_pointer;
+
+	h->free_space_pointer += size;
+	h->free_bytes -= size;
+
+	return (void *)addr;
+}
+
+int early_malloc_active(void)
+{
+	return ((gd->flags & GD_FLG_RELOC) != GD_FLG_RELOC);
+}
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
diff --git a/include/dmmalloc.h b/include/dmmalloc.h
new file mode 100644
index 0000000..a5ce2ec
--- /dev/null
+++ b/include/dmmalloc.h
@@ -0,0 +1,89 @@ 
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck@gmail.com)
+ *
+ * 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 __INCLUDE_DMMALLOC_H
+#define __INCLUDE_DMMALLOC_H
+
+#include <config.h>
+#include <linux/stddef.h> /* for size_t */
+#include <malloc.h>
+
+#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
+	(!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
+#undef CONFIG_SYS_EARLY_MALLOC
+#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+struct early_heap_header {
+	void *free_space_pointer;
+	size_t free_bytes;
+	void *next_early_heap;
+};
+
+struct early_heap_header *early_brk(size_t size);
+void *early_malloc(size_t size);
+int early_malloc_active(void);
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_DM
+
+static inline void *dmmalloc(size_t size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return early_malloc(size);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return malloc(size);
+}
+
+static inline void dmfree(void *ptr)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	free(ptr);
+}
+
+static inline void *dmcalloc(size_t n, size_t elem_size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return NULL;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return calloc(n, elem_size);
+}
+
+static inline void *dmrealloc(void *oldmem, size_t bytes)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return NULL;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return dmrealloc(oldmem, bytes);
+}
+
+#endif /* CONFIG_DM */
+#endif /* __INCLUDE_DMMALLOC_H */
+