Author: stepan Date: Thu Mar 25 23:15:19 2010 New Revision: 5298 URL: https://tracker.coreboot.org/trac/coreboot/changeset/5298
Log: 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 stepan@coresystems.de Acked-by: Joseph Smith joe@settoplinux.org
Added: trunk/payloads/libpayload/libc/args.c Modified: trunk/payloads/libpayload/Config.in trunk/payloads/libpayload/include/getopt.h trunk/payloads/libpayload/include/libpayload.h trunk/payloads/libpayload/include/powerpc/arch/endian.h trunk/payloads/libpayload/libc/Makefile.inc trunk/payloads/libpayload/libc/malloc.c trunk/payloads/libpayload/libc/string.c
Modified: trunk/payloads/libpayload/Config.in ============================================================================== --- trunk/payloads/libpayload/Config.in Thu Mar 25 22:45:25 2010 (r5297) +++ trunk/payloads/libpayload/Config.in Thu Mar 25 23:15:19 2010 (r5298) @@ -30,6 +30,31 @@
mainmenu "Libpayload Configuration"
+menu "Generic Options" + +config EXPERIMENTAL + bool "Experimental Options" + default n + help + Prompt for experimental functionality. Attention: This is not likely + to work without problems + +config OBSOLETE + bool "Obsolete Options" + default n + help + Prompt for obsolete options. These options are for old, unsupported + features and are likely to go away in the future. + +config DEVELOPER + bool "Developer Options" + default n + help + Prompt for developer options. These options are only interesting for + libpayload developers. + +endmenu + menu "Architecture Options"
choice @@ -65,6 +90,18 @@ bool "Enable tinycurses support" default y
+config LAR + bool "LAR support" + default n + depends on OBSOLETE + help + LAR is the archive format of (obsolete) coreboot v3 + +config CBFS + bool "CBFS support" + default y + help + CBFS is the archive format of (obsolete) coreboot v3 endmenu
menu "Console Options" @@ -197,19 +234,52 @@ NOTE: This option is not (fully) implemented yet
config USB_HID - bool "Support for USB keyboards (broken)" + bool "Support for USB keyboards" depends on USB - default n + default y + help + Select this option if you want to use devices complying to the + USB HID (Human Interface Device) standard. Such devices are for + example keyboards and mice. Currently only keyboards are supported. + Say Y here unless you know exactly what you are doing.
config USB_HUB - bool "Support for USB hubs (broken)" + bool "Support for USB hubs" depends on USB - default n + default y + help + Select this option if you want to compile in support for USB hubs. + Say Y here unless you know exactly what you are doing.
config USB_MSC bool "Support for USB storage" depends on USB + default y + help + Select this option if you want to compile in support for USB mass + storage devices (USB memory sticks, hard drives, CDROM/DVD drives) + Say Y here unless you know exactly what you are doing. + +endmenu + +menu "Debugging" + depends on DEVELOPER + +config DEBUG_MALLOC + bool "Debug memory allocator" + depends on USB + default n + help + Select this option if you want to debug the memory allocator. This + option logs all uses of the following functions: + + void free(void *ptr); + void *malloc(size_t size); + void *calloc(size_t nmemb, size_t size); + void *realloc(void *ptr, size_t size); + void *memalign(size_t align, size_t size);
+ Say N here unless you are debugging memory allocator problems.
endmenu
Modified: trunk/payloads/libpayload/include/getopt.h ============================================================================== --- trunk/payloads/libpayload/include/getopt.h Thu Mar 25 22:45:25 2010 (r5297) +++ trunk/payloads/libpayload/include/getopt.h Thu Mar 25 23:15:19 2010 (r5298) @@ -75,4 +75,9 @@ #endif //__END_DECLS
+#define MAX_ARGS 16 +extern char *string_argv[MAX_ARGS]; +extern int string_argc; +int string_to_args(char *caller, char *string); + #endif /* !_GETOPT_H_ */
Modified: trunk/payloads/libpayload/include/libpayload.h ============================================================================== --- trunk/payloads/libpayload/include/libpayload.h Thu Mar 25 22:45:25 2010 (r5297) +++ trunk/payloads/libpayload/include/libpayload.h Thu Mar 25 23:15:19 2010 (r5298) @@ -43,14 +43,17 @@ #ifndef _LIBPAYLOAD_H #define _LIBPAYLOAD_H
+#include <libpayload-config.h> #include <stddef.h> #include <arch/types.h> #include <arch/io.h> #include <arch/virtual.h> #include <sysinfo.h> #include <stdarg.h> -#include <lar.h> #include <pci.h> +#ifdef CONFIG_LAR +#include <lar.h> +#endif
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) @@ -253,11 +256,82 @@ * @defgroup malloc Memory allocation functions * @{ */ +#if defined(CONFIG_DEBUG_MALLOC) && !defined(IN_MALLOC_C) +#define free(p) \ + ({ \ + extern void print_malloc_map(void); \ + extern void free(void *); \ + printf("free(%p) called from %s:%s:%d...\n", p, __FILE__, __func__, \ + __LINE__);\ + printf("PRE free()\n"); \ + print_malloc_map(); \ + free(p); \ + printf("POST free()\n"); \ + print_malloc_map(); \ + }) +#define malloc(s) \ + ({ \ + extern void print_malloc_map(void); \ + extern void *malloc(size_t); \ + void *ptr; \ + printf("malloc(%u) called from %s:%s:%d...\n", s, __FILE__, __func__, \ + __LINE__);\ + printf("PRE malloc\n"); \ + print_malloc_map(); \ + ptr = malloc(s); \ + printf("POST malloc (ptr = %p)\n", ptr); \ + print_malloc_map(); \ + ptr; \ + }) +#define calloc(n,s) \ + ({ \ + extern void print_malloc_map(void); \ + extern void *calloc(size_t,size_t); \ + void *ptr; \ + printf("calloc(%u, %u) called from %s:%s:%d...\n", n, s, __FILE__, \ + __func__, __LINE__);\ + printf("PRE calloc\n"); \ + print_malloc_map(); \ + ptr = calloc(n,s); \ + printf("POST calloc (ptr = %p)\n", ptr); \ + print_malloc_map(); \ + ptr; \ + }) +#define realloc(p,s) \ + ({ \ + extern void print_malloc_map(void); \ + extern void *realloc(void*,size_t); \ + void *ptr; \ + printf("realloc(%p, %u) called from %s:%s:%d...\n", p, s, __FILE__, \ + __func__, __LINE__);\ + printf("PRE realloc\n"); \ + print_malloc_map(); \ + ptr = realloc(p,s); \ + printf("POST realloc (ptr = %p)\n", ptr); \ + print_malloc_map(); \ + ptr; \ + }) +#define memalign(a,s) \ + ({ \ + extern void print_malloc_map(void); \ + extern void *memalign(size_t, size_t); \ + void *ptr; \ + printf("memalign(%u, %u) called from %s:%s:%d...\n", a, s, __FILE__, \ + __func__, __LINE__);\ + printf("PRE memalign\n"); \ + print_malloc_map(); \ + ptr = memalign(a,s); \ + printf("POST realloc (ptr = %p)\n", ptr); \ + print_malloc_map(); \ + ptr; \ + }) +#else void free(void *ptr); void *malloc(size_t size); void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); void *memalign(size_t align, size_t size); +#endif /** @} */
/** @@ -341,7 +415,9 @@ char *strncpy(char *d, const char *s, size_t n); char *strcpy(char *d, const char *s); char *strncat(char *d, const char *s, size_t n); +size_t strlcat(char *d, const char *s, size_t n); char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); char *strdup(const char *s); char *strstr(const char *h, const char *n); char *strsep(char **stringp, const char *delim); @@ -363,6 +439,7 @@ int gettimeofday(struct timeval *tv, void *tz); /** @} */
+#ifdef CONFIG_LAR /** * @defgroup lar LAR functions * @{ @@ -421,6 +498,7 @@ int lfseek(struct LFILE *stream, long offset, int whence); int lfclose(struct LFILE *file); /** @} */ +#endif
/** * @defgroup info System information functions
Modified: trunk/payloads/libpayload/include/powerpc/arch/endian.h ============================================================================== --- trunk/payloads/libpayload/include/powerpc/arch/endian.h Thu Mar 25 22:45:25 2010 (r5297) +++ trunk/payloads/libpayload/include/powerpc/arch/endian.h Thu Mar 25 23:15:19 2010 (r5298) @@ -38,4 +38,8 @@
#define ntohll(in) (in)
+#define htonw(in) ntohw(in) +#define htonl(in) ntohw(in) +#define htonll(in) ntohll(in) + #endif
Modified: trunk/payloads/libpayload/libc/Makefile.inc ============================================================================== --- trunk/payloads/libpayload/libc/Makefile.inc Thu Mar 25 22:45:25 2010 (r5297) +++ trunk/payloads/libpayload/libc/Makefile.inc Thu Mar 25 23:15:19 2010 (r5298) @@ -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
Added: trunk/payloads/libpayload/libc/args.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/payloads/libpayload/libc/args.c Thu Mar 25 23:15:19 2010 (r5298) @@ -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 <libpayload.h> +#include <getopt.h> + +/* 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; +}
Modified: trunk/payloads/libpayload/libc/malloc.c ============================================================================== --- trunk/payloads/libpayload/libc/malloc.c Thu Mar 25 22:45:25 2010 (r5297) +++ trunk/payloads/libpayload/libc/malloc.c Thu Mar 25 23:15:19 2010 (r5298) @@ -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 <libpayload.h>
extern char _heap, _eheap; /* Defined in the ldscript. */ @@ -66,11 +68,21 @@ 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 @@ 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 @@
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 @@ 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 @@ { 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 @@ }
/* 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 @@ (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
Modified: trunk/payloads/libpayload/libc/string.c ============================================================================== --- trunk/payloads/libpayload/libc/string.c Thu Mar 25 22:45:25 2010 (r5297) +++ trunk/payloads/libpayload/libc/string.c Thu Mar 25 23:15:19 2010 (r5298) @@ -171,7 +171,9 @@ 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++) @@ -182,6 +184,30 @@ }
/** + * 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. * * @param s The string. @@ -197,6 +223,27 @@ if (*p == c) return p; } + + 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; }