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>




git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5298 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Stefan Reinauer 2010-03-25 22:15:19 +00:00 committed by Stefan Reinauer
parent 516a2a7bfa
commit e5d30b78b7
8 changed files with 361 additions and 16 deletions

View File

@ -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 @@ config TINYCURSES
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 @@ config USB_EHCI
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

View File

@ -75,4 +75,9 @@ extern char *suboptarg; /* getsubopt(3) external variable */
#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_ */

View File

@ -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 @@ unsigned short ipchksum(const void *ptr, unsigned long nbytes);
* @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 @@ int strncmp(const char *s1, const char *s2, size_t maxlen);
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 @@ struct timeval {
int gettimeofday(struct timeval *tv, void *tz);
/** @} */
#ifdef CONFIG_LAR
/**
* @defgroup lar LAR functions
* @{
@ -421,6 +498,7 @@ int lfread(void *ptr, size_t size, size_t nmemb, struct LFILE *stream);
int lfseek(struct LFILE *stream, long offset, int whence);
int lfclose(struct LFILE *file);
/** @} */
#endif
/**
* @defgroup info System information functions

View File

@ -38,4 +38,8 @@
#define ntohll(in) (in)
#define htonw(in) ntohw(in)
#define htonl(in) ntohw(in)
#define htonll(in) ntohll(in)
#endif

View File

@ -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

View File

@ -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;
}

View File

@ -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 @@ 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)) {
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

View File

@ -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.
*