On 10/29/12 00:20, Tomas Hlavacek wrote: > Add pointer to the first early heap into GD structure. > Implement simple early_malloc and early_free functions. > Prepare for additional heaps and automated heap initialization. > Add temporary early_malloc_active function (to be replaced in future by > more coarse DM init flags). > Add DM specific malloc calls - dmmalloc, dmfree, dmrealloc and dmcalloc. > > Signed-off-by: Tomas Hlavacek <tmshl...@gmail.com> > --- > Changes in v10: > - Change GD type to struct early_heap_header *. > - Move dmmalloc, dmfree, ... function from .h to dmmalloc.c . > - Rework early_malloc_active() to use new GD_FLG_HEAP_INIT flag. > - Add early_heap_active() and GD_FLG_EARLY_HEAP_DONE flag. > - Rework dmrealloc() and dmfree() to use new flags and support relocation. > - Rename early_heap_dump() to early_malloc_heap_dump(). > - Add early_malloc_dump. > - Drop conditional undef CONFIG_SYS_EARLY_MALLOC in dmmalloc.h. > - Moved struct early_block_header and macros to dmmalloc.c. > > Changes in v9: > - Rework early_malloc to keep track of allocated block size. > - Add early_free and dmfree functions. > - Rework dmrealloc. > > Changes in v8: > - Add dmcalloc() implementation. > - Add comments to function prototypes in dmmalloc.h. > > Changes in v7: > - Rework check of first heap in early_brk(). > > Changes in v6: > - Move dmmalloc() and all dm* functions to dmmalloc.h. > - Fix bool expression in early_malloc_active(). > > arch/arm/include/asm/global_data.h | 8 + > arch/avr32/include/asm/global_data.h | 7 + > arch/blackfin/include/asm/global_data.h | 6 + > arch/m68k/include/asm/global_data.h | 8 + > arch/microblaze/include/asm/global_data.h | 8 + > arch/mips/include/asm/global_data.h | 6 + > arch/nds32/include/asm/global_data.h | 8 + > arch/nios2/include/asm/global_data.h | 7 + > arch/openrisc/include/asm/global_data.h | 8 + > arch/powerpc/include/asm/global_data.h | 6 + > arch/sandbox/include/asm/global_data.h | 7 + > arch/sh/include/asm/global_data.h | 7 + > arch/sparc/include/asm/global_data.h | 6 + > arch/x86/include/asm/global_data.h | 8 + > common/Makefile | 1 + > common/dmmalloc.c | 297 > +++++++++++++++++++++++++++++ > include/asm-generic/global_data_flags.h | 6 +- > include/dmmalloc.h | 132 +++++++++++++ > 18 files changed, 534 insertions(+), 2 deletions(-) > create mode 100644 common/dmmalloc.c > create mode 100644 include/dmmalloc.h > > diff --git a/arch/arm/include/asm/global_data.h > b/arch/arm/include/asm/global_data.h > index 2b9af93..01075dc 100644 > --- a/arch/arm/include/asm/global_data.h > +++ b/arch/arm/include/asm/global_data.h > @@ -23,6 +23,11 @@ > > #ifndef __ASM_GBL_DATA_H > #define __ASM_GBL_DATA_H > + > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > /* > * The following data structure is placed in some memory which is > * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or > @@ -82,6 +87,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 > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/avr32/include/asm/global_data.h > b/arch/avr32/include/asm/global_data.h > index bf661e2..ba9cf0e 100644 > --- a/arch/avr32/include/asm/global_data.h > +++ b/arch/avr32/include/asm/global_data.h > @@ -22,6 +22,10 @@ > #ifndef __ASM_GLOBAL_DATA_H__ > #define __ASM_GLOBAL_DATA_H__ > > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > /* > * The following data structure is placed in some memory wich is > * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or > @@ -48,6 +52,9 @@ typedef struct global_data { > #endif > void **jt; /* jump table */ > char env_buf[32]; /* buffer for getenv() before reloc. */ > +#ifdef CONFIG_SYS_EARLY_MALLOC > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/blackfin/include/asm/global_data.h > b/arch/blackfin/include/asm/global_data.h > index d91e5a4..daeb314 100644 > --- a/arch/blackfin/include/asm/global_data.h > +++ b/arch/blackfin/include/asm/global_data.h > @@ -29,6 +29,9 @@ > #define __ASM_GBL_DATA_H > > #include <asm/u-boot.h> > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > > /* > * The following data structure is placed in some memory wich is > @@ -57,6 +60,9 @@ typedef struct global_data { > > void **jt; /* jump table */ > char env_buf[32]; /* buffer for getenv() before reloc. */ > +#ifdef CONFIG_SYS_EARLY_MALLOC > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/m68k/include/asm/global_data.h > b/arch/m68k/include/asm/global_data.h > index 0cdb11c..dad2ba5 100644 > --- a/arch/m68k/include/asm/global_data.h > +++ b/arch/m68k/include/asm/global_data.h > @@ -23,6 +23,11 @@ > > #ifndef __ASM_GBL_DATA_H > #define __ASM_GBL_DATA_H > + > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > /* > * The following data structure is placed in some memory wich is > * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or > @@ -66,6 +71,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 > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/microblaze/include/asm/global_data.h > b/arch/microblaze/include/asm/global_data.h > index 2111c7c..f6609b8 100644 > --- a/arch/microblaze/include/asm/global_data.h > +++ b/arch/microblaze/include/asm/global_data.h > @@ -24,6 +24,11 @@ > > #ifndef __ASM_GBL_DATA_H > #define __ASM_GBL_DATA_H > + > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > /* > * The following data structure is placed in some memory wich is > * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or > @@ -46,6 +51,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 > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/mips/include/asm/global_data.h > b/arch/mips/include/asm/global_data.h > index a735a8a..c9b76f6 100644 > --- a/arch/mips/include/asm/global_data.h > +++ b/arch/mips/include/asm/global_data.h > @@ -25,6 +25,9 @@ > #define __ASM_GBL_DATA_H > > #include <asm/regdef.h> > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > > /* > * The following data structure is placed in some memory wich is > @@ -59,6 +62,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 > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/nds32/include/asm/global_data.h > b/arch/nds32/include/asm/global_data.h > index b1feb2c..6d972c2 100644 > --- a/arch/nds32/include/asm/global_data.h > +++ b/arch/nds32/include/asm/global_data.h > @@ -33,6 +33,11 @@ > > #ifndef __ASM_GBL_DATA_H > #define __ASM_GBL_DATA_H > + > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > /* > * The following data structure is placed in some memory wich is > * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or > @@ -63,6 +68,9 @@ typedef struct global_data { > > void **jt; /* jump table */ > char env_buf[32]; /* buffer for getenv() before reloc. */ > +#ifdef CONFIG_SYS_EARLY_MALLOC > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/nios2/include/asm/global_data.h > b/arch/nios2/include/asm/global_data.h > index 413b485..441e566 100644 > --- a/arch/nios2/include/asm/global_data.h > +++ b/arch/nios2/include/asm/global_data.h > @@ -23,6 +23,10 @@ > #ifndef __ASM_NIOS2_GLOBALDATA_H_ > #define __ASM_NIOS2_GLOBALDATA_H_ > > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > typedef struct global_data { > bd_t *bd; > unsigned long flags; > @@ -42,6 +46,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 > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/openrisc/include/asm/global_data.h > b/arch/openrisc/include/asm/global_data.h > index 96f3f1c..94fcef1 100644 > --- a/arch/openrisc/include/asm/global_data.h > +++ b/arch/openrisc/include/asm/global_data.h > @@ -24,6 +24,11 @@ > > #ifndef __ASM_GBL_DATA_H > #define __ASM_GBL_DATA_H > + > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > /* > * The following data structure is placed in some memory wich is > * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or > @@ -44,6 +49,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 > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/powerpc/include/asm/global_data.h > b/arch/powerpc/include/asm/global_data.h > index 374fc6d..ed67bfd 100644 > --- a/arch/powerpc/include/asm/global_data.h > +++ b/arch/powerpc/include/asm/global_data.h > @@ -26,6 +26,9 @@ > > #include "config.h" > #include "asm/types.h" > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > > /* > * The following data structure is placed in some memory wich is > @@ -182,6 +185,9 @@ typedef struct global_data { > #endif > void **jt; /* jump table */ > char env_buf[32]; /* buffer for getenv() before reloc. */ > +#ifdef CONFIG_SYS_EARLY_MALLOC > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/sandbox/include/asm/global_data.h > b/arch/sandbox/include/asm/global_data.h > index 78a751d..0d4b4b0 100644 > --- a/arch/sandbox/include/asm/global_data.h > +++ b/arch/sandbox/include/asm/global_data.h > @@ -33,6 +33,10 @@ > * up the memory controller so that we can use RAM). > */ > > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > typedef struct global_data { > bd_t *bd; > unsigned long flags; > @@ -46,6 +50,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 > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/sh/include/asm/global_data.h > b/arch/sh/include/asm/global_data.h > index 9a2c193..acacae7 100644 > --- a/arch/sh/include/asm/global_data.h > +++ b/arch/sh/include/asm/global_data.h > @@ -27,6 +27,10 @@ > #ifndef __ASM_SH_GLOBALDATA_H_ > #define __ASM_SH_GLOBALDATA_H_ > > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > typedef struct global_data > { > bd_t *bd; > @@ -42,6 +46,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 > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/sparc/include/asm/global_data.h > b/arch/sparc/include/asm/global_data.h > index aa63b35..aad97e1 100644 > --- a/arch/sparc/include/asm/global_data.h > +++ b/arch/sparc/include/asm/global_data.h > @@ -28,6 +28,9 @@ > #define __ASM_GBL_DATA_H > > #include "asm/types.h" > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > > /* > * The following data structure is placed in some memory wich is > @@ -74,6 +77,9 @@ typedef struct global_data { > #endif > void **jt; /* jump table */ > char env_buf[32]; /* buffer for getenv() before reloc. */ > +#ifdef CONFIG_SYS_EARLY_MALLOC > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > #include <asm-generic/global_data_flags.h> > diff --git a/arch/x86/include/asm/global_data.h > b/arch/x86/include/asm/global_data.h > index bce999f..9eff403 100644 > --- a/arch/x86/include/asm/global_data.h > +++ b/arch/x86/include/asm/global_data.h > @@ -23,6 +23,11 @@ > > #ifndef __ASM_GBL_DATA_H > #define __ASM_GBL_DATA_H > + > +#ifdef CONFIG_SYS_EARLY_MALLOC > +#include <dmmalloc.h> > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > /* > * The following data structure is placed in some memory wich is > * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or > @@ -57,6 +62,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 > + struct early_heap_header *early_heap; /* heap for early_malloc */ > +#endif > } gd_t; > > static inline gd_t *get_fs_gd_ptr(void) > diff --git a/common/Makefile b/common/Makefile > index fdfead7..bfb4d7a 100644 > --- a/common/Makefile > +++ b/common/Makefile > @@ -209,6 +209,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..4a1a241 > --- /dev/null > +++ b/common/dmmalloc.c > @@ -0,0 +1,297 @@ > +/* > + * (C) Copyright 2012 > + * Tomas Hlavacek (tmshl...@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 > + > +struct early_block_header { > + size_t size; > +}; > + > +#define BLOCK_DATA(header) ((void *)(((struct early_block_header > *)header)+1)) > +#define BLOCK_HEADER(addr) (((struct early_block_header *)addr)-1) > +#define BLOCK_USED_FLAG 0x80000000 > +#define BLOCK_SIZE(size) (size & (~BLOCK_USED_FLAG)) > +#define BLOCK_USED(size) ((size & BLOCK_USED_FLAG) == BLOCK_USED_FLAG) > +#define BLOCK_FREE(size) (!BLOCK_USED(size)) > +#define BLOCK_SET_FREE(size) BLOCK_SIZE(size) > +#define BLOCK_SET_USED(size) (size | BLOCK_USED_FLAG) > + > + > +__weak struct early_heap_header *early_brk(size_t size) > +{ > + struct early_heap_header *h; > + struct early_block_header *b; > + > + if (gd->early_heap != NULL) > + return NULL; > + > + h = (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR; > + b = (struct early_block_header *)(h + 1); > + > + size = CONFIG_SYS_EARLY_HEAP_SIZE; > + h->size = size; > + h->early_heap_next = NULL; > + b->size = size - sizeof(struct early_heap_header) - > + sizeof(struct early_block_header); > + b->size = BLOCK_SET_FREE(b->size); > + > + return h; > +} > + > +static struct early_block_header *find_free_space(struct early_heap_header > *h, > + size_t size) > +{ > + struct early_block_header *b; > + > + b = (struct early_block_header *)(h+1); > + while ((phys_addr_t)b + sizeof(struct early_block_header) > + < (phys_addr_t)h + h->size) { > + if (BLOCK_FREE(b->size) && (BLOCK_SIZE(b->size) >= size)) > + return b; > + b = (struct early_block_header *)((phys_addr_t)b + > + sizeof(struct early_block_header) + > + BLOCK_SIZE(b->size)); > + } > + > + return NULL; > +} > + > +static struct early_block_header *split_block(struct early_block_header *b, > + size_t size) > +{ > + struct early_block_header *nb; > + > + if ((BLOCK_SIZE(b->size) < size) || (BLOCK_USED(b->size))) > + return NULL; > + > + if (BLOCK_SIZE(b->size) <= (size + sizeof(struct early_block_header))) > + return b; > + > + nb = (struct early_block_header *)((phys_addr_t)b + > + sizeof(struct early_block_header) + size); > + nb->size = b->size - size - sizeof(struct early_block_header); > + b->size = size; > + > + return b; > +} > + > +void *early_malloc(size_t size) > +{ > + struct early_heap_header *h; > + struct early_block_header *b; > + > + size = roundup(size, sizeof(phys_addr_t)); > + if (size == 0) > + return NULL; > + > + if (gd->early_heap == NULL) > + gd->early_heap = early_brk(size); > + > + if (gd->early_heap == NULL) { > + debug("early_brk failed to initialize heap\n"); > + return NULL; > + } > + > + h = gd->early_heap; > + while (1) { > + b = find_free_space(h, size); > + if (b != NULL) > + break; > + > + if (h->early_heap_next != NULL) > + h = h->early_heap_next; > + else > + break; > + } > + > + if (b == NULL) { > + h->early_heap_next = early_brk(size+ > + sizeof(struct early_heap_header)+ > + sizeof(struct early_block_header)); > + h = h->early_heap_next; > + if (h == NULL) { > + debug("early_brk failed to extend heap by %d B\n", > + size); > + return NULL; > + } > + > + b = find_free_space(h, size); > + if (b == NULL) { > + debug("early_malloc failed to extend heap by %d B\n", > + size); > + return NULL; > + } > + } > + > + if (b->size != size) > + b = split_block(b, size); > + if (b == NULL) { > + debug("early_malloc failed to split block to %d B\n", size); > + return NULL; > + } > + > + b->size = BLOCK_SET_USED(b->size); > + > + return BLOCK_DATA(b); > +} > + > +void early_free(void *addr) > +{ > + struct early_block_header *h = BLOCK_HEADER(addr); > + assert(BLOCK_USED(h->size)); > + h->size = BLOCK_SET_FREE(h->size); > +} > + > +void early_malloc_heap_dump(struct early_heap_header *h) > +{ > + struct early_block_header *b; > + > + debug("heap: h=%p, h->size=%d\n", h, h->size); > + > + b = (struct early_block_header *)(h+1); > + while ((phys_addr_t)b + sizeof(struct early_block_header) > + < (phys_addr_t)h + h->size) { > + debug("block: h=%p h->size=%d b=%p b->size=%d b->(used)=%d\n", > + h, h->size, b, BLOCK_SIZE(b->size), > + BLOCK_USED(b->size)); > + assert(BLOCK_SIZE(b->size) > 0); > + b = (struct early_block_header *)((phys_addr_t)b + > + sizeof(struct early_block_header) + > + BLOCK_SIZE(b->size)); > + } > + debug("--- heap dump end ---\n"); > +} > + > +void early_malloc_dump(void) > +{ > + struct early_heap_header *h = gd->early_heap; > + while (h != NULL) { > + early_malloc_heap_dump(h); > + h = h->early_heap_next; > + } > +} > + > +static int early_malloc_active(void) > +{ > + return ((gd->flags & GD_FLG_HEAP_INIT) != GD_FLG_HEAP_INIT); > +} > + > +static int early_heap_active(void) > +{ > + return ((gd->flags & GD_FLG_EARLY_HEAP_DONE) != > + GD_FLG_EARLY_HEAP_DONE); > +} > + > +static int early_address(void *ptr) > +{ > + struct early_heap_header *h = gd->early_heap; > + while (h != NULL) { > + if (((phys_addr_t)ptr >= (phys_addr_t)h) && > + ((phys_addr_t)ptr < (phys_addr_t)h + h->size)) > + return 1; > + > + h = h->early_heap_next; > + } > + > + return 0; > +} > + > + > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > + > +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); > +} > + > +void dmfree(void *ptr) > +{ > +#ifdef CONFIG_SYS_EARLY_MALLOC > + if (early_heap_active()) { > + if (early_address(ptr)) > + early_free(ptr); > + return; > + } > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + free(ptr); > +} > + > +void *dmcalloc(size_t n, size_t elem_size) > +{ > +#ifdef CONFIG_SYS_EARLY_MALLOC > + char *addr; > + int size = elem_size * n; > + > + if (early_malloc_active()) { > + addr = early_malloc(size); > + memset(addr, 0, size); > + return addr; > + } > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + return calloc(n, elem_size); > +} > + > +void *dmrealloc(void *oldaddr, size_t bytes) > +{ > +#ifdef CONFIG_SYS_EARLY_MALLOC > + char *addr; > + struct early_block_header *h; > + > + if (early_heap_active() && early_address(oldaddr)) { > + addr = dmmalloc(bytes); > + if (addr == NULL) > + return NULL; > + > + h = BLOCK_HEADER(oldaddr); > + if (BLOCK_FREE(h->size)) > + return NULL; > + > + if (bytes > BLOCK_SIZE(h->size)) > + bytes = BLOCK_SIZE(h->size); > + > + memcpy(addr, oldaddr, bytes); > + dmfree(oldaddr); > + return addr; > + } > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + return realloc(oldaddr, bytes); > +} > + > diff --git a/include/asm-generic/global_data_flags.h > b/include/asm-generic/global_data_flags.h > index bb57fb6..97db2c2 100644 > --- a/include/asm-generic/global_data_flags.h > +++ b/include/asm-generic/global_data_flags.h > @@ -13,8 +13,8 @@ > /* > * Global Data Flags > * > - * Note: The low 16 bits are expected for common code. If your arch > - * really needs to add your own, use the high 16bits. > + * Note: The low 18 bits are expected for common code. If your arch > + * really needs to add your own, use the high 14 bits. > */ > #define GD_FLG_RELOC 0x0001 /* Code was relocated to RAM */ > #define GD_FLG_DEVINIT 0x0002 /* Devices have been > initialized */ > @@ -24,5 +24,7 @@ > #define GD_FLG_LOGINIT 0x0020 /* Log Buffer has been > initialized */ > #define GD_FLG_DISABLE_CONSOLE 0x0040 /* Disable console (in & out) */ > #define GD_FLG_ENV_READY 0x0080 /* Environment imported into hash table > */ > +#define GD_FLG_HEAP_INIT 0x0100 /* malloc() in RAM is available */ > +#define GD_FLG_EARLY_HEAP_DONE 0x0200 /* early_malloc() heap > relocated. */ > > #endif > diff --git a/include/dmmalloc.h b/include/dmmalloc.h > new file mode 100644 > index 0000000..c99f423 > --- /dev/null > +++ b/include/dmmalloc.h > @@ -0,0 +1,132 @@ > +/* > + * (C) Copyright 2012 > + * Tomas Hlavacek (tmshl...@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> > + > +#ifdef CONFIG_SYS_EARLY_MALLOC > + > +/** > + * struct early_heap_header - header preceding an early heap > + * @size - length of the heap in bytes (including the heap header). > + * @early_heap_next - pointer to the following heap. > + * > + * Heaps are organized in the single direction linked list. Each heap > + * contains own size. Pointer to the first (left-most) heap is > + * contained in global data. > + */ > +struct early_heap_header { > + size_t size; > + void *early_heap_next; > +}; > + > +/** > + * early_brk() - obtain address of the heap > + * @size: Minimal size of the new early heap to be allocated. > + * > + * Function returns a new heap pointer. > + * > + * Allocate and initialize early_heap at least size bytes long. > + * This function can be platform dependent or board dependent but sensible > + * default is provided. > + */ > +struct early_heap_header *early_brk(size_t size); > + > +/** > + * early_malloc() - malloc operating on the early_heap(s) > + * @size: Size in bytes. > + * > + * Function returns a pointer to the allocated block. > + */ > +void *early_malloc(size_t size); > + > +/** > + * early_free() - free operating on the early_heap(s) > + * @addr: Pointer to the allocated block to be released. > + */ > +void early_free(void *addr); > + > +/** > + * early_malloc_heap_dump() - print blocks contained in an early_heap > + * @h: Address of the early heap. > + */ > +void early_malloc_heap_dump(struct early_heap_header *h); > + > +/** > + * early_malloc_dump() - print blocks contained in all early_heaps > + */ > +void early_malloc_dump(void); > + > + > +#endif /* CONFIG_SYS_EARLY_MALLOC */ > + > +#ifdef CONFIG_DM > + > +/* > + * DM versions of malloc* functions. In early init it calls early_malloc. > + * It wraps around normal malloc* functions afterwards. > + */ > + > +/** > + * dmmalloc() - malloc working seamlessly in early as well as in RAM stages > + * @size: Size of the block to be allocated. > + * > + * Function returns an address of the newly allocated block when successful > + * or NULL otherwise. > + */ > +void *dmmalloc(size_t size); > + > +/** > + * dmfree() - free working seamlessly in early as well as in RAM stages > + * @ptr: Pointer to the allocated block to be released. > + */ > +void dmfree(void *ptr); > + > +/** > + * dmcalloc() - calloc working seamlessly in early as well as in RAM stages > + * @n: Number of elements to be allocated. > + * @elem_size: Size of elements to be allocated. > + * > + * Function returns a pointer to newly the allocated area (n*elem_size) long. > + */ > +void *dmcalloc(size_t n, size_t elem_size); > + > +/** > + * dmrealloc() - realloc working seamlessly in early as well as in RAM stages > + * @oldaddr: Pointer to the old memory block. > + * @bytes: New size to of the block to be reallocated. > + * > + * Function returns an address of the newly allocated block when successful > + * or NULL otherwise. > + * > + * Data are copied from the block specified by oldaddr to the new block. > + */ > +void *dmrealloc(void *oldaddr, size_t bytes); > + > +#endif /* CONFIG_DM */ > +#endif /* __INCLUDE_DMMALLOC_H */ > + >
*you may stop your scrolling now* Hello, does it ring a bell? I need to get it (or an equivalent solution) to work before implementing a working DM2-I2C uclass. I don't see any replies to the original v10 e-mail. Why wasn't it accepted into U-Boot? Should I work on top of this patch, or start from scratch? Regards, _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot