From e5d30b78b7720ba3e511819b7fc51c11d642153b Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Thu, 25 Mar 2010 22:15:19 +0000 Subject: libpayload update * rework Config.in * add string_to_args function to actually make getopt usable. * add strchr * add strlcat * some malloc fixes (exposed by the USB stack) * add malloc debugging (thanks to Matthias Krause from Secunet!) * make LAR support optional, it's not really used anymore * (define htoX macros for ppc) Signed-off-by: Stefan Reinauer Acked-by: Joseph Smith git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5298 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- payloads/libpayload/libc/Makefile.inc | 7 ++- payloads/libpayload/libc/args.c | 88 +++++++++++++++++++++++++++++++++++ payloads/libpayload/libc/malloc.c | 64 +++++++++++++++++++++---- payloads/libpayload/libc/string.c | 49 ++++++++++++++++++- 4 files changed, 198 insertions(+), 10 deletions(-) create mode 100644 payloads/libpayload/libc/args.c (limited to 'payloads/libpayload/libc') diff --git a/payloads/libpayload/libc/Makefile.inc b/payloads/libpayload/libc/Makefile.inc index 82906c7132..3cd98c9b98 100644 --- a/payloads/libpayload/libc/Makefile.inc +++ b/payloads/libpayload/libc/Makefile.inc @@ -30,5 +30,10 @@ TARGETS-$(CONFIG_LIBC) += libc/malloc.o libc/printf.o libc/console.o libc/string.o TARGETS-$(CONFIG_LIBC) += libc/memory.o libc/ctype.o libc/ipchecksum.o libc/lib.o -TARGETS-$(CONFIG_LIBC) += libc/rand.o libc/time.o libc/lar.o libc/exec.o +TARGETS-$(CONFIG_LIBC) += libc/rand.o libc/time.o libc/exec.o TARGETS-$(CONFIG_LIBC) += libc/readline.o libc/getopt_long.o libc/sysinfo.o +TARGETS-$(CONFIG_LIBC) += libc/args.o + +# should be moved to coreboot directory +TARGETS-$(CONFIG_LAR) += libc/lar.o +#TARGETS-$(CONFIG_CBFS) += libc/cbfs.o diff --git a/payloads/libpayload/libc/args.c b/payloads/libpayload/libc/args.c new file mode 100644 index 0000000000..8242d60bba --- /dev/null +++ b/payloads/libpayload/libc/args.c @@ -0,0 +1,88 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 coresystems GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * @file libc/readline.c + * Simple readline implementation + */ + +#include +#include + +/* We don't want to waste malloc on this, so we live with a small + * fixed size array + */ +char *string_argv[MAX_ARGS]; +int string_argc; + +/** + * Take a string and make char *argv[] and int argc from it. + * + * This function allows the user to use getopt on an arbitrary string. + * + * global variables valid after a successful run of string_to_args(): + * string_argc pointer to number of arguments + * string_argv pointer to argument list. + * + * @param caller to be used as argv[0] (may be NULL to ignore) + * @param string to process + * @return 0 if no error occured. + */ +int string_to_args(char *caller, char *string) +{ + int i = 0; + + if (caller) + string_argv[i++] = caller; + + if (*string) + string_argv[i++] = string; + + /* Terminate if the string ends */ + while (string && *string) { + /* whitespace occured? */ + if ((*string == ' ') || (*string == '\t')) { + /* skip all whitespace (and null it) */ + while (*string == ' ' || *string == '\t') + *string++ = 0; + /* if our ugly static array is big enough, store + * argument to string_argv[] + */ + if (i < MAX_ARGS) + string_argv[i++] = string; + } + string++; + } + + /* prevent array from overflowing */ + string_argc = (i <= MAX_ARGS) ? i : MAX_ARGS; + + /* and return whether there was an overflow */ + return (i <= MAX_ARGS) ? 0 : 1; +} diff --git a/payloads/libpayload/libc/malloc.c b/payloads/libpayload/libc/malloc.c index 28b0974752..9e1dd2e575 100644 --- a/payloads/libpayload/libc/malloc.c +++ b/payloads/libpayload/libc/malloc.c @@ -2,6 +2,7 @@ * This file is part of the libpayload project. * * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008-2010 coresystems GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,6 +39,7 @@ * your buffers, kids!). */ +#define IN_MALLOC_C #include extern char _heap, _eheap; /* Defined in the ldscript. */ @@ -66,11 +68,21 @@ typedef unsigned int hdrtype_t; static int free_aligned(void* addr); void print_malloc_map(void); +#ifdef CONFIG_DEBUG_MALLOC +static int heap_initialized = 0; +static int minimal_free = 0; +#endif + static void setup(void) { int size = (unsigned int)(&_eheap - &_heap) - HDRSIZE; *((hdrtype_t *) hstart) = FREE_BLOCK(size); + +#ifdef CONFIG_DEBUG_MALLOC + heap_initialized = 1; + minimal_free = size; +#endif } static void *alloc(int len) @@ -94,7 +106,9 @@ static void *alloc(int len) int size = SIZE(header); if (!HAS_MAGIC(header) || size == 0) { - printf("memory allocator panic.\n"); + printf("memory allocator panic. (%s%s)\n", + !HAS_MAGIC(header) ? " no magic " : "", + size == 0 ? " size=0 " : ""); halt(); } @@ -268,9 +282,16 @@ struct align_region_t static struct align_region_t* align_regions = 0; -static struct align_region_t *allocate_region(struct align_region_t *old_first, int alignment, int num_elements) +static struct align_region_t *allocate_region(int alignment, int num_elements) { - struct align_region_t *new_region = malloc(sizeof(struct align_region_t)); + struct align_region_t *new_region; +#ifdef CONFIG_DEBUG_MALLOC + printf("%s(old align_regions=%p, alignment=%u, num_elements=%u)\n", + __func__, align_regions, alignment, num_elements); +#endif + + new_region = malloc(sizeof(struct align_region_t)); + if (!new_region) return NULL; new_region->alignment = alignment; @@ -282,8 +303,9 @@ static struct align_region_t *allocate_region(struct align_region_t *old_first, new_region->start_data = (void*)((u32)(new_region->start + num_elements + alignment - 1) & (~(alignment-1))); new_region->size = num_elements * alignment; new_region->free = num_elements; - new_region->next = old_first; + new_region->next = align_regions; memset(new_region->start, 0, num_elements); + align_regions = new_region; return new_region; } @@ -325,15 +347,29 @@ look_further: { if ((reg->alignment == align) && (reg->free >= (size + align - 1)/align)) { +#ifdef CONFIG_DEBUG_MALLOC + printf(" found memalign region. %x free, %x required\n", reg->free, (size + align - 1)/align); +#endif break; } reg = reg->next; } if (reg == 0) { - align_regions = allocate_region(align_regions, align, (size/align<99)?100:((size/align)+1)); - reg = align_regions; +#ifdef CONFIG_DEBUG_MALLOC + printf(" need to allocate a new memalign region\n"); +#endif + /* get align regions */ + reg = allocate_region(align, (size<1024)?(1024/align):(((size-1)/align)+1)); +#ifdef CONFIG_DEBUG_MALLOC + printf(" ... returned %p\n", align_regions); +#endif + } + if (reg == 0) { + /* Nothing available. */ + return (void *)NULL; } + int i, count = 0, target = (size+align-1)/align; for (i = 0; i < (reg->size/align); i++) { @@ -358,16 +394,20 @@ look_further: } /* This is for debugging purposes. */ -#ifdef TEST +#ifdef CONFIG_DEBUG_MALLOC void print_malloc_map(void) { void *ptr = hstart; + int free_memory = 0; while (ptr < hend) { hdrtype_t hdr = *((hdrtype_t *) ptr); if (!HAS_MAGIC(hdr)) { - printf("Poisoned magic - we're toast\n"); + if (heap_initialized) + printf("Poisoned magic - we're toast\n"); + else + printf("No magic yet - going to initialize\n"); break; } @@ -377,7 +417,15 @@ void print_malloc_map(void) (unsigned int)(ptr - hstart), hdr & FLAG_FREE ? "FREE" : "USED", SIZE(hdr)); + if (hdr & FLAG_FREE) + free_memory += SIZE(hdr); + ptr += HDRSIZE + SIZE(hdr); } + + if (free_memory && (minimal_free > free_memory)) + minimal_free = free_memory; + printf("Maximum memory consumption: %d bytes", + (unsigned int)(&_eheap - &_heap) - HDRSIZE - minimal_free); } #endif diff --git a/payloads/libpayload/libc/string.c b/payloads/libpayload/libc/string.c index 81cce26a61..b69fab6815 100644 --- a/payloads/libpayload/libc/string.c +++ b/payloads/libpayload/libc/string.c @@ -171,7 +171,9 @@ char *strcpy(char *d, const char *s) char *strncat(char *d, const char *s, size_t n) { char *p = d + strlen(d); - int max = n > strlen(s) ? strlen(s) : n; + int sl = strlen(s); + int max = n > sl ? sl : n; + // int max = n > strlen(s) ? strlen(s) : n; int i; for (i = 0; i < max; i++) @@ -181,6 +183,30 @@ char *strncat(char *d, const char *s, size_t n) return d; } +/** + * Concatenates two strings with a maximum length. + * + * @param d The destination string. + * @param s The source string. + * @param n Not more than n characters from s will be appended to d. + * @return A pointer to the destination string. + */ +size_t strlcat(char *d, const char *s, size_t n) +{ + int sl = strlen(s); + int dl = strlen(d); + + char *p = d + dl; + int max = n > (sl + dl) ? sl : (n - dl - 1); + int i; + + for (i = 0; i < max; i++) + p[i] = s[i]; + + p[i] = '\0'; + return max; +} + /** * Find a character in a string. * @@ -201,6 +227,27 @@ char *strchr(const char *s, int c) return NULL; } +/** + * Find a character in a string. + * + * @param s The string. + * @param c The character. + * @return A pointer to the last occurence of the character in the + * string, or NULL if the character was not encountered within the string. + */ + +char *strrchr(const char *s, int c) +{ + char *p = (char *)s + strlen(s); + + for (; p >= s; p--) { + if (*p == c) + return p; + } + + return NULL; +} + /** * Duplicate a string. * -- cgit v1.2.3