From f6145c3c15789123f6b4a9ce64a517048e753762 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Wed, 19 Mar 2008 23:56:58 +0000 Subject: libpayload: The initial chunk of code writen by AMD This is the initial chunk of code written by me and copyrighted by AMD. Includes everything but a few files that we pulled from outside sources. Signed-off-by: Jordan Crouse Acked-by: Uwe Hermann git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3170 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- payloads/libpayload/libc/Makefile.inc | 32 +++++ payloads/libpayload/libc/console.c | 104 ++++++++++++++ payloads/libpayload/libc/ctype.c | 60 ++++++++ payloads/libpayload/libc/malloc.c | 262 ++++++++++++++++++++++++++++++++++ payloads/libpayload/libc/string.c | 195 +++++++++++++++++++++++++ 5 files changed, 653 insertions(+) create mode 100644 payloads/libpayload/libc/Makefile.inc create mode 100644 payloads/libpayload/libc/console.c create mode 100644 payloads/libpayload/libc/ctype.c create mode 100644 payloads/libpayload/libc/malloc.c create mode 100644 payloads/libpayload/libc/string.c (limited to 'payloads/libpayload/libc') diff --git a/payloads/libpayload/libc/Makefile.inc b/payloads/libpayload/libc/Makefile.inc new file mode 100644 index 0000000000..f42f836174 --- /dev/null +++ b/payloads/libpayload/libc/Makefile.inc @@ -0,0 +1,32 @@ +# +# This file is part of the libpayload project. +# +# Copyright (C) 2008 Advanced Micro Devices, Inc. +# +# 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. +# + +TARGETS-y += libc/malloc.o libc/printf.o libc/console.o libc/string.o +TARGETS-y += libc/memory.o libc/ctype.o +TARGETS-y += libc/ipchecksum.o diff --git a/payloads/libpayload/libc/console.c b/payloads/libpayload/libc/console.c new file mode 100644 index 0000000000..bb7dec1f94 --- /dev/null +++ b/payloads/libpayload/libc/console.c @@ -0,0 +1,104 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + */ + +#include + +void console_init(void) +{ +#ifdef CONFIG_VGA_CONSOLE + vga_init(); +#endif +#ifdef CONFIG_SERIAL_CONSOLE + serial_init(); +#endif +} + +static void device_putchar(unsigned char c) +{ +#ifdef CONFIG_VGA_CONSOLE + vga_putchar(0x700| c); +#endif +#ifdef CONFIG_SERIAL_CONSOLE + serial_putchar(c); +#endif +} + +int putchar(int c) +{ + c &= 0xff; + if (c == '\n') + device_putchar('\r'); + device_putchar(c); + return c; +} + +int puts(const char *s) +{ + int n = 0; + + while (*s) { + putchar(*s++); + n++; + } + + putchar('\n'); + return n+1; +} + +int havekey(void) +{ +#ifdef CONFIG_SERIAL_CONSOLE + if (serial_havechar()) + return 1; +#endif +#ifdef CONFIG_PC_KEYBOARD + if (keyboard_havechar()) + return 1; +#endif + return 0; +} + +/* This returns an ascii value - the two getchar functions + cook the respective input from the device +*/ + +int getchar(void) +{ + while (1) { +#ifdef CONFIG_SERIAL_CONSOLE + if (serial_havechar()) + return serial_getchar(); +#endif +#ifdef CONFIG_PC_KEYBOARD + if (keyboard_havechar()) + return keyboard_getchar(); +#endif + } +} + diff --git a/payloads/libpayload/libc/ctype.c b/payloads/libpayload/libc/ctype.c new file mode 100644 index 0000000000..c2f42a52d2 --- /dev/null +++ b/payloads/libpayload/libc/ctype.c @@ -0,0 +1,60 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + */ + +/* Basic ctype functions */ + +#include + +int isspace(int c) +{ + switch (c) { + case ' ': case '\f': case '\n': + case '\r': case '\t': case '\v': + return 1; + default: + return 0; + } +} + +int isdigit(int c) +{ + switch (c) { + case '0'...'9': + return 1; + default: + return 0; + } +} + +int tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + return c - 'A' + 'a'; + return c; +} diff --git a/payloads/libpayload/libc/malloc.c b/payloads/libpayload/libc/malloc.c new file mode 100644 index 0000000000..a4877e67d9 --- /dev/null +++ b/payloads/libpayload/libc/malloc.c @@ -0,0 +1,262 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + */ + +/* This is a classically weak malloc() implmentation. + We have a relatively small and static heap, so we take + the easy route with an O(N) loop through the tree for + every malloc() and free(). Obviously, this doesn't scale + past a few hundred K (if that). + + We're also susecptable to the usual buffer overun poisoning, + though the risk is within acceptable ranges for this + implementation (don't overrun your buffers, kids!) +*/ + +#include + +/* Defined in the ldscript */ +extern char _heap, _eheap; + +static void *hstart = (void *) &_heap; +static void *hend = (void *) &_eheap; + +typedef unsigned int hdrtype_t; + +#define MAGIC (0x2a << 26) +#define FLAG_FREE (1 << 25) +#define FLAG_USED (1 << 24) + +#define SIZE(_h) ((_h) & 0xFFFFFF) + +#define _HEADER(_s, _f) ((hdrtype_t) (MAGIC | (_f) | ((_s) & 0xFFFFFF))) + +#define FREE_BLOCK(_s) _HEADER(_s, FLAG_FREE) +#define USED_BLOCK(_s) _HEADER(_s, FLAG_USED) + +#define HDRSIZE (sizeof(hdrtype_t)) + +#define IS_FREE(_h) (((_h) & (MAGIC | FLAG_FREE)) == (MAGIC | FLAG_FREE)) +#define HAS_MAGIC(_h) (((_h) & MAGIC) == MAGIC) + +void print_malloc_map(void); + +static void setup(void) +{ + int size = (unsigned int) (_heap - _eheap) - HDRSIZE; + *((hdrtype_t *) hstart) = FREE_BLOCK(size); +} + +static void *alloc(int len) +{ + hdrtype_t header; + void *ptr = hstart; + + /* align the size */ + len = (len + 3) & ~3; + + if (!len || len > 0xFFFFFF) + return (void *) NULL; + + /* Make sure the region is setup correctly */ + if (!HAS_MAGIC(*((hdrtype_t *) ptr))) + setup(); + + /* Find some free space */ + + do { + header = *((hdrtype_t *) ptr); + int size = SIZE(header); + + if (header & FLAG_FREE) { + + if (len <= size) { + void *nptr = ptr + HDRSIZE + len; + int nsize = size - (len + 8); + + /* Mark the block as used */ + *((hdrtype_t *) ptr) = USED_BLOCK(len); + + /* If there is still room in this block, + * then mark it as such */ + + if (nsize > 0) + *((hdrtype_t *) nptr) = + FREE_BLOCK(nsize - 4); + + return (void *) (ptr + HDRSIZE); + } + } + + ptr += HDRSIZE + size; + + } while(ptr < hend); + + /* Nothing available */ + return (void *) NULL; +} + +static void _consolidate(void) +{ + void *ptr = hstart; + + while(ptr < hend) { + void *nptr; + hdrtype_t hdr = *((hdrtype_t *) ptr); + unsigned int size = 0; + + if (!IS_FREE(hdr)) { + ptr += HDRSIZE + SIZE(hdr); + continue; + } + + size = SIZE(hdr); + nptr = ptr + HDRSIZE + SIZE(hdr); + + while (nptr < hend) { + hdrtype_t nhdr = *((hdrtype_t *) nptr); + + if (!(IS_FREE(nhdr))) + break; + + size += SIZE(nhdr) + HDRSIZE; + + *((hdrtype_t *) nptr) = 0; + + nptr += (HDRSIZE + SIZE(nhdr)); + } + + *((hdrtype_t *) ptr) = FREE_BLOCK(size); + ptr = nptr; + } +} + +void free(void *ptr) +{ + hdrtype_t hdr; + + ptr -= HDRSIZE; + + /* Sanity check */ + if (ptr < hstart || ptr >= hend) + return; + + hdr = *((hdrtype_t *) ptr); + + /* Not our header (we're probably poisoned) */ + if (!HAS_MAGIC(hdr)) + return; + + /* Double free */ + if (hdr & FLAG_FREE) + return; + + *((hdrtype_t *) ptr) = FREE_BLOCK(SIZE(hdr)); + _consolidate(); +} + +void *malloc(size_t size) +{ + return alloc(size); +} + +void *calloc(size_t nmemb, size_t size) +{ + unsigned int total = (nmemb * size); + void *ptr = alloc(size); + + if (ptr) + memset(ptr, 0, total); + + return ptr; +} + +void *realloc(void *ptr, size_t size) +{ + void *ret; + void *pptr; + unsigned int osize; + + if (ptr == NULL) + return alloc(size); + + pptr = ptr - HDRSIZE; + + if (!HAS_MAGIC(*((hdrtype_t *) pptr))) + return NULL; + + /* Get the original size of the block */ + osize = SIZE(*((hdrtype_t *) pptr)); + + /* Free the memory to update the tables - this + won't touch the actual memory, so we can still + use it for the copy after we have reallocated + the new space + */ + + free(ptr); + ret = alloc(size); + + /* if ret == NULL, then doh - failure. + if ret == ptr then woo-hoo! no copy needed */ + + if (ret == NULL || ret == ptr) + return ret; + + /* Copy the memory to the new location */ + memcpy(ret, ptr, osize > size ? size : osize); + return ret; +} + +/* This is for debugging purposes */ +#ifdef TEST + +void print_malloc_map(void) +{ + void *ptr = hstart; + + while(ptr < hend) { + hdrtype_t hdr = *((hdrtype_t *) ptr); + + if (!HAS_MAGIC(hdr)) { + printf("Poisoned magic - we're toast\n"); + break; + } + + /* FIXME: Verify the size of the block */ + + printf("%x: %s (%x bytes)\n", + (unsigned int) (ptr - hstart), + hdr & FLAG_FREE ? "FREE" : "USED", + SIZE(hdr)); + + ptr += HDRSIZE + SIZE(hdr); + } +} + +#endif diff --git a/payloads/libpayload/libc/string.c b/payloads/libpayload/libc/string.c new file mode 100644 index 0000000000..c9f0603387 --- /dev/null +++ b/payloads/libpayload/libc/string.c @@ -0,0 +1,195 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2007 Uwe Hermann + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + */ + +#include +#include + +/** + * Calculate the length of a fixed-size string. + * + * @param str The input string. + * @param maxlen Return at most maxlen characters as length of the string. + * @return The length of the string, not including the final NUL character. + * The maximum length returned is maxlen. + */ +size_t strnlen(const char *str, size_t maxlen) +{ + size_t len = 0; + + /* NULL and empty strings have length 0. */ + if (!str) + return 0; + + /* Loop until we find a NUL character, or maxlen is reached. */ + while ((*str++ != '\0') && (len < maxlen)) + len++; + + return len; +} + +/** + * Calculate the length of a string. + * + * @param str The input string. + * @return The length of the string, not including the final NUL character. + */ +size_t strlen(const char *str) +{ + size_t len = 0; + + /* NULL and empty strings have length 0. */ + if (!str) + return 0; + + /* Loop until we find a NUL character. */ + while (*str++ != '\0') + len++; + + return len; +} + +/** + * Compare two strings. + * + * @param s1 The first string. + * @param s2 The second string. + * @return Returns a value less than zero, if s1 is shorter than s2. Returns + * zero, if s1 equals s2. Returns a value greater than zero, if + * s1 is longer than s2. + */ +int strcmp(const char *s1, const char *s2) +{ + char c1, c2; + + /* Set c1 == c2, so that we can enter the while loop. */ + c1 = 0; + c2 = 0; + + /* Compare characters until they differ, or one of the strings ends. */ + while (c1 == c2) { + /* Read the next character from each string. */ + c1 = *s1++; + c2 = *s2++; + + /* Return something negative (if s1 is shorter than s2), or + zero (if s1 equals s2). */ + if (c1 == '\0') + return c1 - c2; + } + + /* Return someting positive (if s1 is longer than s2), or zero (if s1 + and s2 are equal). */ + return c1 - c2; +} + +/** + * Compare two strings with fixed length. + * + * @param s1 The first string. + * @param s2 The second string. + * @param maxlen Return at most maxlen characters as length of the string. + * @return A non-zero value if s1 and s2 differ, or zero if s1 equals s2. + */ +int strncmp(const char *s1, const char *s2, int maxlen) +{ + int i; + + for (i = 0; i < maxlen; i++) { + if (s1[i] != s2[i]) + return s1[i] - s2[i]; + } + + return 0; +} + +char *strncpy(char *d, const char *s, int n) +{ + /* use +1 to get the null terminator */ + + int max = n > strlen(s) + 1 ? strlen(s) + 1 : n; + int i; + + for(i = 0; i < max; i++) + d[i] = (char) s[i]; + + return d; +} + +char *strncat(char *d, const char *s, int n) +{ + char *p = d + strlen(d); + int max = n > strlen(s) ? strlen(s) : n; + int i; + + for(i = 0; i < max; i++) + p[i] = s[i]; + + p[i] = '\0'; + return d; +} + +char * strchr(const char *s, int c) +{ + char *p = (char *) s; + + for( ; *p != 0; p++) { + if (*p == c) + return p; + } + + return NULL; +} + + +char *strdup(const char *s) +{ + int n = strlen(s); + char *p = malloc(n); + + if (p != NULL) + strncpy(p, s, n); + + return p; +} + +char *strstr(const char *h, const char *n) +{ + int hn = strlen(h); + int nn = strlen(n); + int i; + + for(i = 0; i <= hn - nn; i++) + if (!strcmp(&h[i], n)) + return (char *) &h[i]; + + return NULL; +} + + -- cgit v1.2.3