From 16c11c04efa7a903b5366706bbe315a6ccf9ec34 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 16 Jun 2020 19:24:07 +0930 Subject: [PATCH 1/3] fusesoc: Add XC750T variant Signed-off-by: Joel Stanley --- microwatt.core | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/microwatt.core b/microwatt.core index 83d7762..055c8a9 100644 --- a/microwatt.core +++ b/microwatt.core @@ -177,6 +177,21 @@ targets: vivado: {part : xc7a35ticsg324-1L} toplevel : toplevel + arty_a7-50: + default_tool: vivado + filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram] + parameters : + - memory_size + - ram_init_file + - use_litedram=true + - disable_flatten_core + - no_bram + - spi_flash_offset=3145728 + generate: [dram_arty] + tools: + vivado: {part : xc7a50ticsg324-1L} + toplevel : toplevel + arty_a7-100-nodram: default_tool: vivado filesets: [core, arty_a7, soc, fpga, debug_xilinx, xilinx_specific] From 5d8f2e221a435831821b92fb79266aacab976418 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Mon, 22 Jun 2020 16:42:01 +0930 Subject: [PATCH 2/3] Add libc This is a copy of litedram/gen-src/sdram_init/libc. We should work out how to share the sources. Signed-off-by: Joel Stanley --- loader/libc/include/assert.h | 29 ++++ loader/libc/include/compiler.h | 54 ++++++ loader/libc/include/ctype.h | 26 +++ loader/libc/include/errno.h | 36 ++++ loader/libc/include/limits.h | 32 ++++ loader/libc/include/stdint.h | 30 ++++ loader/libc/include/stdio.h | 35 ++++ loader/libc/include/stdlib.h | 25 +++ loader/libc/include/string.h | 45 +++++ loader/libc/include/unistd.h | 26 +++ loader/libc/src/isdigit.c | 26 +++ loader/libc/src/isprint.c | 19 +++ loader/libc/src/isspace.c | 30 ++++ loader/libc/src/isxdigit.c | 22 +++ loader/libc/src/memchr.c | 28 +++ loader/libc/src/memcmp.c | 29 ++++ loader/libc/src/memcpy.c | 36 ++++ loader/libc/src/memmove.c | 36 ++++ loader/libc/src/memset.c | 40 +++++ loader/libc/src/strcasecmp.c | 27 +++ loader/libc/src/strcat.c | 26 +++ loader/libc/src/strchr.c | 28 +++ loader/libc/src/strcmp.c | 25 +++ loader/libc/src/strcpy.c | 23 +++ loader/libc/src/strlen.c | 40 +++++ loader/libc/src/strncasecmp.c | 30 ++++ loader/libc/src/strncmp.c | 30 ++++ loader/libc/src/strncpy.c | 33 ++++ loader/libc/src/strrchr.c | 28 +++ loader/libc/src/strstr.c | 39 +++++ loader/libc/src/strtok.c | 48 ++++++ loader/libc/src/strtol.c | 113 ++++++++++++ loader/libc/src/strtoul.c | 103 +++++++++++ loader/libc/src/tolower.c | 19 +++ loader/libc/src/toupper.c | 21 +++ loader/libc/src/vsnprintf.c | 304 +++++++++++++++++++++++++++++++++ 36 files changed, 1541 insertions(+) create mode 100644 loader/libc/include/assert.h create mode 100644 loader/libc/include/compiler.h create mode 100644 loader/libc/include/ctype.h create mode 100644 loader/libc/include/errno.h create mode 100644 loader/libc/include/limits.h create mode 100644 loader/libc/include/stdint.h create mode 100644 loader/libc/include/stdio.h create mode 100644 loader/libc/include/stdlib.h create mode 100644 loader/libc/include/string.h create mode 100644 loader/libc/include/unistd.h create mode 100644 loader/libc/src/isdigit.c create mode 100644 loader/libc/src/isprint.c create mode 100644 loader/libc/src/isspace.c create mode 100644 loader/libc/src/isxdigit.c create mode 100644 loader/libc/src/memchr.c create mode 100644 loader/libc/src/memcmp.c create mode 100644 loader/libc/src/memcpy.c create mode 100644 loader/libc/src/memmove.c create mode 100644 loader/libc/src/memset.c create mode 100644 loader/libc/src/strcasecmp.c create mode 100644 loader/libc/src/strcat.c create mode 100644 loader/libc/src/strchr.c create mode 100644 loader/libc/src/strcmp.c create mode 100644 loader/libc/src/strcpy.c create mode 100644 loader/libc/src/strlen.c create mode 100644 loader/libc/src/strncasecmp.c create mode 100644 loader/libc/src/strncmp.c create mode 100644 loader/libc/src/strncpy.c create mode 100644 loader/libc/src/strrchr.c create mode 100644 loader/libc/src/strstr.c create mode 100644 loader/libc/src/strtok.c create mode 100644 loader/libc/src/strtol.c create mode 100644 loader/libc/src/strtoul.c create mode 100644 loader/libc/src/tolower.c create mode 100644 loader/libc/src/toupper.c create mode 100644 loader/libc/src/vsnprintf.c diff --git a/loader/libc/include/assert.h b/loader/libc/include/assert.h new file mode 100644 index 0000000..2c49fd7 --- /dev/null +++ b/loader/libc/include/assert.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008, 2012 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _ASSERT_H +#define _ASSERT_H + +#define assert(cond) \ + do { if (!(cond)) { \ + assert_fail(__FILE__ \ + ":" stringify(__LINE__) \ + ":" stringify(cond)); } \ + } while(0) + +void __attribute__((noreturn)) assert_fail(const char *msg); + +#define stringify(expr) stringify_1(expr) +/* Double-indirection required to stringify expansions */ +#define stringify_1(expr) #expr + +#endif diff --git a/loader/libc/include/compiler.h b/loader/libc/include/compiler.h new file mode 100644 index 0000000..c36b14f --- /dev/null +++ b/loader/libc/include/compiler.h @@ -0,0 +1,54 @@ +/* Copyright 2013-2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __COMPILER_H +#define __COMPILER_H + +#ifndef __ASSEMBLY__ + +#include + +/* Macros for various compiler bits and pieces */ +#define __packed __attribute__((packed)) +#define __align(x) __attribute__((__aligned__(x))) +#define __unused __attribute__((unused)) +#define __used __attribute__((used)) +#define __section(x) __attribute__((__section__(x))) +#define __noreturn __attribute__((noreturn)) +/* not __const as this has a different meaning (const) */ +#define __attrconst __attribute__((const)) +#define __warn_unused_result __attribute__((warn_unused_result)) +#define __noinline __attribute__((noinline)) + +#if 0 /* Provided by gcc stddef.h */ +#define offsetof(type,m) __builtin_offsetof(type,m) +#endif + +#define __nomcount __attribute__((no_instrument_function)) + +/* Compiler barrier */ +static inline void barrier(void) +{ +// asm volatile("" : : : "memory"); +} + +#endif /* __ASSEMBLY__ */ + +/* Stringification macro */ +#define __tostr(x) #x +#define tostr(x) __tostr(x) + +#endif /* __COMPILER_H */ diff --git a/loader/libc/include/ctype.h b/loader/libc/include/ctype.h new file mode 100644 index 0000000..60c98b0 --- /dev/null +++ b/loader/libc/include/ctype.h @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _CTYPE_H +#define _CTYPE_H + +#include + +int __attrconst isdigit(int c); +int __attrconst isxdigit(int c); +int __attrconst isprint(int c); +int __attrconst isspace(int c); + +int __attrconst tolower(int c); +int __attrconst toupper(int c); + +#endif diff --git a/loader/libc/include/errno.h b/loader/libc/include/errno.h new file mode 100644 index 0000000..c2bd987 --- /dev/null +++ b/loader/libc/include/errno.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _ERRNO_H +#define _ERRNO_H + +extern int errno; + +/* + * Error number definitions + */ +#define EPERM 1 /* not permitted */ +#define ENOENT 2 /* file or directory not found */ +#define EIO 5 /* input/output error */ +#define EBADF 9 /* Bad file number */ +#define ENOMEM 12 /* not enough space */ +#define EACCES 13 /* permission denied */ +#define EFAULT 14 /* bad address */ +#define EBUSY 16 /* resource busy */ +#define EEXIST 17 /* file already exists */ +#define ENODEV 19 /* device not found */ +#define EINVAL 22 /* invalid argument */ +#define EDOM 33 /* math argument out of domain of func */ +#define ERANGE 34 /* math result not representable */ +#define ENOSYS 38 /* Function not implemented */ + +#endif diff --git a/loader/libc/include/limits.h b/loader/libc/include/limits.h new file mode 100644 index 0000000..4726835 --- /dev/null +++ b/loader/libc/include/limits.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _LIMITS_H +#define _LIMITS_H + +#define UCHAR_MAX 255 +#define SCHAR_MAX 127 +#define SCHAR_MIN (-128) + +#define USHRT_MAX 65535 +#define SHRT_MAX 32767 +#define SHRT_MIN (-32768) + +#define UINT_MAX (4294967295U) +#define INT_MAX 2147483647 +#define INT_MIN (-2147483648) + +#define ULONG_MAX ((unsigned long)-1L) +#define LONG_MAX (ULONG_MAX/2) +#define LONG_MIN ((-LONG_MAX)-1) + +#endif diff --git a/loader/libc/include/stdint.h b/loader/libc/include/stdint.h new file mode 100644 index 0000000..2a2c1d9 --- /dev/null +++ b/loader/libc/include/stdint.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDINT_H +#define _STDINT_H + +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +typedef unsigned long int uintptr_t; + +#endif diff --git a/loader/libc/include/stdio.h b/loader/libc/include/stdio.h new file mode 100644 index 0000000..764d755 --- /dev/null +++ b/loader/libc/include/stdio.h @@ -0,0 +1,35 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDIO_H +#define _STDIO_H + +#include +#include "stddef.h" + +#define EOF (-1) + +int _printf(const char *format, ...) __attribute__((format (printf, 1, 2))); + +#ifndef pr_fmt +#define pr_fmt(fmt) fmt +#endif + +#define printf(f, ...) do { _printf(pr_fmt(f), ##__VA_ARGS__); } while(0) + +int snprintf(char *str, size_t size, const char *format, ...) __attribute__((format (printf, 3, 4))); +int vsnprintf(char *str, size_t size, const char *format, va_list); + +int putchar(int ch); +int puts(const char *str); + +#endif diff --git a/loader/libc/include/stdlib.h b/loader/libc/include/stdlib.h new file mode 100644 index 0000000..f5d8b31 --- /dev/null +++ b/loader/libc/include/stdlib.h @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDLIB_H +#define _STDLIB_H + +#include "stddef.h" + +#define RAND_MAX 32767 + +int atoi(const char *str); +long atol(const char *str); +unsigned long int strtoul(const char *nptr, char **endptr, int base); +long int strtol(const char *nptr, char **endptr, int base); + +#endif diff --git a/loader/libc/include/string.h b/loader/libc/include/string.h new file mode 100644 index 0000000..2172bdc --- /dev/null +++ b/loader/libc/include/string.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Copyright (c) 2004, 2016 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STRING_H +#define _STRING_H + +#include "stddef.h" + +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); +char *strcat(char *dest, const char *src); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +int strcasecmp(const char *s1, const char *s2); +int strncasecmp(const char *s1, const char *s2, size_t n); +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); +size_t strlen(const char *s); +size_t strnlen(const char *s, size_t n); +char *strstr(const char *hay, const char *needle); +char *strtok(char *src, const char *pattern); +char *strdup(const char *src); + +void *memset(void *s, int c, size_t n); +void *memchr(const void *s, int c, size_t n); +void *memcpy(void *dest, const void *src, size_t n); +void *memcpy_from_ci(void *destpp, const void *srcpp, size_t len); +void *memmove(void *dest, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); + +static inline int ffs(unsigned long val) +{ + return __builtin_ffs(val); +} + +#endif diff --git a/loader/libc/include/unistd.h b/loader/libc/include/unistd.h new file mode 100644 index 0000000..bc53472 --- /dev/null +++ b/loader/libc/include/unistd.h @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include + +typedef long ssize_t; + +extern int open(const char *name, int flags); +extern int close(int fd); +extern ssize_t read(int fd, void *buf, size_t count); +extern ssize_t write(int fd, const void *buf, size_t count); +extern ssize_t lseek(int fd, long offset, int whence); + +#endif diff --git a/loader/libc/src/isdigit.c b/loader/libc/src/isdigit.c new file mode 100644 index 0000000..68cd4eb --- /dev/null +++ b/loader/libc/src/isdigit.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include + +int __attrconst isdigit(int ch) +{ + switch (ch) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return 1; + + default: + return 0; + } +} diff --git a/loader/libc/src/isprint.c b/loader/libc/src/isprint.c new file mode 100644 index 0000000..0a7c94c --- /dev/null +++ b/loader/libc/src/isprint.c @@ -0,0 +1,19 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include + +int __attrconst isprint(int ch) +{ + return (ch >= 32 && ch < 127); +} diff --git a/loader/libc/src/isspace.c b/loader/libc/src/isspace.c new file mode 100644 index 0000000..f9fa36a --- /dev/null +++ b/loader/libc/src/isspace.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include + +int __attrconst isspace(int ch) +{ + switch (ch) { + case ' ': + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + return 1; + + default: + return 0; + } +} diff --git a/loader/libc/src/isxdigit.c b/loader/libc/src/isxdigit.c new file mode 100644 index 0000000..d3c7388 --- /dev/null +++ b/loader/libc/src/isxdigit.c @@ -0,0 +1,22 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include + +int __attrconst isxdigit(int ch) +{ + return ( + (ch >= '0' && ch <= '9') | + (ch >= 'A' && ch <= 'F') | + (ch >= 'a' && ch <= 'f') ); +} diff --git a/loader/libc/src/memchr.c b/loader/libc/src/memchr.c new file mode 100644 index 0000000..db9a147 --- /dev/null +++ b/loader/libc/src/memchr.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +void *memchr(const void *ptr, int c, size_t n); +void *memchr(const void *ptr, int c, size_t n) +{ + unsigned char ch = (unsigned char)c; + const unsigned char *p = ptr; + + while (n-- > 0) { + if (*p == ch) + return (void *)p; + p += 1; + } + + return NULL; +} diff --git a/loader/libc/src/memcmp.c b/loader/libc/src/memcmp.c new file mode 100644 index 0000000..b270b59 --- /dev/null +++ b/loader/libc/src/memcmp.c @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +int memcmp(const void *ptr1, const void *ptr2, size_t n); +int memcmp(const void *ptr1, const void *ptr2, size_t n) +{ + const unsigned char *p1 = ptr1; + const unsigned char *p2 = ptr2; + + while (n-- > 0) { + if (*p1 != *p2) + return (*p1 - *p2); + p1 += 1; + p2 += 1; + } + + return 0; +} diff --git a/loader/libc/src/memcpy.c b/loader/libc/src/memcpy.c new file mode 100644 index 0000000..3ab0490 --- /dev/null +++ b/loader/libc/src/memcpy.c @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include + +void *memcpy(void *dest, const void *src, size_t n); +void *memcpy(void *dest, const void *src, size_t n) +{ + void *ret = dest; + + while (n >= 8) { + *(uint64_t *)dest = *(uint64_t *)src; + dest += 8; + src += 8; + n -= 8; + } + + while (n > 0) { + *(uint8_t *)dest = *(uint8_t *)src; + dest += 1; + src += 1; + n -= 1; + } + + return ret; +} diff --git a/loader/libc/src/memmove.c b/loader/libc/src/memmove.c new file mode 100644 index 0000000..76aef6c --- /dev/null +++ b/loader/libc/src/memmove.c @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +void *memcpy(void *dest, const void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n) +{ + /* Do the buffers overlap in a bad way? */ + if (src < dest && src + n >= dest) { + char *cdest; + const char *csrc; + int i; + + /* Copy from end to start */ + cdest = dest + n - 1; + csrc = src + n - 1; + for (i = 0; i < n; i++) { + *cdest-- = *csrc--; + } + return dest; + } else { + /* Normal copy is possible */ + return memcpy(dest, src, n); + } +} diff --git a/loader/libc/src/memset.c b/loader/libc/src/memset.c new file mode 100644 index 0000000..80eea11 --- /dev/null +++ b/loader/libc/src/memset.c @@ -0,0 +1,40 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#define CACHE_LINE_SIZE 128 + +#include + +void *memset(void *dest, int c, size_t size); +void *memset(void *dest, int c, size_t size) +{ + unsigned char *d = (unsigned char *)dest; + unsigned long big_c = 0; + + if (c) { + big_c = c; + big_c |= (big_c << 8) | big_c; + big_c |= (big_c << 16) | big_c; + big_c |= (big_c << 32) | big_c; + } + while (size >= 8 && c == 0) { + *((unsigned long *)d) = big_c; + d+=8; + size-=8; + } + + while (size-- > 0) { + *d++ = (unsigned char)c; + } + + return dest; +} diff --git a/loader/libc/src/strcasecmp.c b/loader/libc/src/strcasecmp.c new file mode 100644 index 0000000..ba1aedb --- /dev/null +++ b/loader/libc/src/strcasecmp.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +int strcasecmp(const char *s1, const char *s2); +int strcasecmp(const char *s1, const char *s2) +{ + while (*s1 != 0 && *s2 != 0) { + if (toupper(*s1) != toupper(*s2)) + break; + ++s1; + ++s2; + } + + return *s1 - *s2; +} + diff --git a/loader/libc/src/strcat.c b/loader/libc/src/strcat.c new file mode 100644 index 0000000..329cc88 --- /dev/null +++ b/loader/libc/src/strcat.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +size_t strlen(const char *s); +char *strcpy(char *dst, const char *src); +char *strcat(char *dst, const char *src); +char *strcat(char *dst, const char *src) +{ + size_t p; + + p = strlen(dst); + strcpy(&dst[p], src); + + return dst; +} diff --git a/loader/libc/src/strchr.c b/loader/libc/src/strchr.c new file mode 100644 index 0000000..88f25f9 --- /dev/null +++ b/loader/libc/src/strchr.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +char *strchr(const char *s, int c); +char *strchr(const char *s, int c) +{ + char cb = c; + + while (*s != 0) { + if (*s == cb) { + return (char *)s; + } + s += 1; + } + + return NULL; +} diff --git a/loader/libc/src/strcmp.c b/loader/libc/src/strcmp.c new file mode 100644 index 0000000..5afbae2 --- /dev/null +++ b/loader/libc/src/strcmp.c @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +int strcmp(const char *s1, const char *s2); +int strcmp(const char *s1, const char *s2) +{ + while (*s1 != 0 && *s2 != 0) { + if (*s1 != *s2) + break; + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + diff --git a/loader/libc/src/strcpy.c b/loader/libc/src/strcpy.c new file mode 100644 index 0000000..514be17 --- /dev/null +++ b/loader/libc/src/strcpy.c @@ -0,0 +1,23 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +char *strcpy(char *dst, const char *src); +char *strcpy(char *dst, const char *src) +{ + char *ptr = dst; + + do { + *ptr++ = *src; + } while (*src++ != 0); + + return dst; +} diff --git a/loader/libc/src/strlen.c b/loader/libc/src/strlen.c new file mode 100644 index 0000000..f3c5a83 --- /dev/null +++ b/loader/libc/src/strlen.c @@ -0,0 +1,40 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +size_t strlen(const char *s); +size_t strlen(const char *s) +{ + size_t len = 0; + + while (*s != 0) { + len += 1; + s += 1; + } + + return len; +} + +size_t strnlen(const char *s, size_t n); +size_t strnlen(const char *s, size_t n) +{ + size_t len = 0; + + while (*s != 0 && n) { + len += 1; + s += 1; + n--; + } + + return len; +} diff --git a/loader/libc/src/strncasecmp.c b/loader/libc/src/strncasecmp.c new file mode 100644 index 0000000..c6b158e --- /dev/null +++ b/loader/libc/src/strncasecmp.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +int strncasecmp(const char *s1, const char *s2, size_t n); +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n < 1) + return 0; + + while (*s1 != 0 && *s2 != 0 && --n > 0) { + if (toupper(*s1) != toupper(*s2)) + break; + ++s1; + ++s2; + } + + return toupper(*s1) - toupper(*s2); +} + diff --git a/loader/libc/src/strncmp.c b/loader/libc/src/strncmp.c new file mode 100644 index 0000000..a5422c0 --- /dev/null +++ b/loader/libc/src/strncmp.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +int strncmp(const char *s1, const char *s2, size_t n); +int strncmp(const char *s1, const char *s2, size_t n) +{ + if (n < 1) + return 0; + + while (*s1 != 0 && *s2 != 0 && --n > 0) { + if (*s1 != *s2) + break; + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + diff --git a/loader/libc/src/strncpy.c b/loader/libc/src/strncpy.c new file mode 100644 index 0000000..621c89b --- /dev/null +++ b/loader/libc/src/strncpy.c @@ -0,0 +1,33 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +char *strncpy(char *dst, const char *src, size_t n); +char *strncpy(char *dst, const char *src, size_t n) +{ + char *ret = dst; + + /* Copy string */ + while (*src != 0 && n > 0) { + *dst++ = *src++; + n -= 1; + } + + /* strncpy always clears the rest of destination string... */ + while (n > 0) { + *dst++ = 0; + n -= 1; + } + + return ret; +} diff --git a/loader/libc/src/strrchr.c b/loader/libc/src/strrchr.c new file mode 100644 index 0000000..262a682 --- /dev/null +++ b/loader/libc/src/strrchr.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008, 2019 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +char *strrchr(const char *s, int c); +char *strrchr(const char *s, int c) +{ + char *last = NULL; + char cb = c; + + while (*s != 0) { + if (*s == cb) + last = (char *)s; + s += 1; + } + + return last; +} diff --git a/loader/libc/src/strstr.c b/loader/libc/src/strstr.c new file mode 100644 index 0000000..cd9ccae --- /dev/null +++ b/loader/libc/src/strstr.c @@ -0,0 +1,39 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +size_t strlen(const char *s); +int strncmp(const char *s1, const char *s2, size_t n); +char *strstr(const char *hay, const char *needle); +char *strstr(const char *hay, const char *needle) +{ + char *pos; + size_t hlen, nlen; + + if (hay == NULL || needle == NULL) + return NULL; + + hlen = strlen(hay); + nlen = strlen(needle); + if (nlen < 1) + return (char *)hay; + + for (pos = (char *)hay; pos < hay + hlen; pos++) { + if (strncmp(pos, needle, nlen) == 0) { + return pos; + } + } + + return NULL; +} + diff --git a/loader/libc/src/strtok.c b/loader/libc/src/strtok.c new file mode 100644 index 0000000..fcc3fce --- /dev/null +++ b/loader/libc/src/strtok.c @@ -0,0 +1,48 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +char *strtok(char *src, const char *pattern); +char *strtok(char *src, const char *pattern) +{ + static char *nxtTok; + char *retVal = NULL; + + if (!src) { + src = nxtTok; + if (!src) + return retVal; + } + + while (*src) { + const char *pp = pattern; + while (*pp) { + if (*pp == *src) { + break; + } + pp++; + } + if (!*pp) { + if (!retVal) + retVal = src; + else if (!src[-1]) + break; + } else + *src = '\0'; + src++; + } + + nxtTok = src; + + return retVal; +} diff --git a/loader/libc/src/strtol.c b/loader/libc/src/strtol.c new file mode 100644 index 0000000..c7c52af --- /dev/null +++ b/loader/libc/src/strtol.c @@ -0,0 +1,113 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +long int strtol(const char *S, char **PTR,int BASE) +{ + long rval = 0; + short int negative = 0; + short int digit; + // *PTR is S, unless PTR is NULL, in which case i override it with my own ptr + char* ptr; + if (PTR == NULL) + { + //override + PTR = &ptr; + } + // i use PTR to advance through the string + *PTR = (char *) S; + //check if BASE is ok + if ((BASE < 0) || BASE > 36) + { + return 0; + } + // ignore white space at beginning of S + while ((**PTR == ' ') + || (**PTR == '\t') + || (**PTR == '\n') + || (**PTR == '\r') + ) + { + (*PTR)++; + } + // check if S starts with "-" in which case the return value is negative + if (**PTR == '-') + { + negative = 1; + (*PTR)++; + } + // if BASE is 0... determine the base from the first chars... + if (BASE == 0) + { + // if S starts with "0x", BASE = 16, else 10 + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + BASE = 16; + } + else + { + BASE = 10; + } + } + if (BASE == 16) + { + // S may start with "0x" + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + (*PTR)++; + (*PTR)++; + } + } + //until end of string + while (**PTR) + { + if (((**PTR) >= '0') && ((**PTR) <= '9')) + { + //digit (0..9) + digit = **PTR - '0'; + } + else if (((**PTR) >= 'a') && ((**PTR) <='z')) + { + //alphanumeric digit lowercase(a (10) .. z (35) ) + digit = (**PTR - 'a') + 10; + } + else if (((**PTR) >= 'A') && ((**PTR) <='Z')) + { + //alphanumeric digit uppercase(a (10) .. z (35) ) + digit = (**PTR - 'A') + 10; + } + else + { + //end of parseable number reached... + break; + } + if (digit < BASE) + { + rval = (rval * BASE) + digit; + } + else + { + //digit found, but its too big for current base + //end of parseable number reached... + break; + } + //next... + (*PTR)++; + } + if (negative) + { + return rval * -1; + } + //else + return rval; +} diff --git a/loader/libc/src/strtoul.c b/loader/libc/src/strtoul.c new file mode 100644 index 0000000..e6e63ae --- /dev/null +++ b/loader/libc/src/strtoul.c @@ -0,0 +1,103 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +unsigned long int strtoul(const char *S, char **PTR,int BASE) +{ + unsigned long rval = 0; + short int digit; + // *PTR is S, unless PTR is NULL, in which case i override it with my own ptr + char* ptr; + if (PTR == NULL) + { + //override + PTR = &ptr; + } + // i use PTR to advance through the string + *PTR = (char *) S; + //check if BASE is ok + if ((BASE < 0) || BASE > 36) + { + return 0; + } + // ignore white space at beginning of S + while ((**PTR == ' ') + || (**PTR == '\t') + || (**PTR == '\n') + || (**PTR == '\r') + ) + { + (*PTR)++; + } + // if BASE is 0... determine the base from the first chars... + if (BASE == 0) + { + // if S starts with "0x", BASE = 16, else 10 + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + BASE = 16; + } + else + { + BASE = 10; + } + } + if (BASE == 16) + { + // S may start with "0x" + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + (*PTR)++; + (*PTR)++; + } + } + //until end of string + while (**PTR) + { + if (((**PTR) >= '0') && ((**PTR) <='9')) + { + //digit (0..9) + digit = **PTR - '0'; + } + else if (((**PTR) >= 'a') && ((**PTR) <='z')) + { + //alphanumeric digit lowercase(a (10) .. z (35) ) + digit = (**PTR - 'a') + 10; + } + else if (((**PTR) >= 'A') && ((**PTR) <='Z')) + { + //alphanumeric digit uppercase(a (10) .. z (35) ) + digit = (**PTR - 'A') + 10; + } + else + { + //end of parseable number reached... + break; + } + if (digit < BASE) + { + rval = (rval * BASE) + digit; + } + else + { + //digit found, but its too big for current base + //end of parseable number reached... + break; + } + //next... + (*PTR)++; + } + //done + return rval; +} + diff --git a/loader/libc/src/tolower.c b/loader/libc/src/tolower.c new file mode 100644 index 0000000..398a1eb --- /dev/null +++ b/loader/libc/src/tolower.c @@ -0,0 +1,19 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include + +int __attrconst tolower(int c) +{ + return (((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a' ) : c); +} diff --git a/loader/libc/src/toupper.c b/loader/libc/src/toupper.c new file mode 100644 index 0000000..6b52363 --- /dev/null +++ b/loader/libc/src/toupper.c @@ -0,0 +1,21 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include "ctype.h" + +int __attrconst toupper (int cha) +{ + if((cha >= 'a') && (cha <= 'z')) + return(cha - 'a' + 'A'); + return(cha); +} diff --git a/loader/libc/src/vsnprintf.c b/loader/libc/src/vsnprintf.c new file mode 100644 index 0000000..034ccab --- /dev/null +++ b/loader/libc/src/vsnprintf.c @@ -0,0 +1,304 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "ctype.h" +#include + +static const unsigned long long convert[] = { + 0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL +}; + +static int +print_str_fill(char **buffer, size_t bufsize, char *sizec, + const char *str, char c) +{ + size_t i, sizei, len; + char *bstart = *buffer; + + sizei = strtoul(sizec, NULL, 10); + len = strlen(str); + if (sizei > len) { + for (i = 0; + (i < (sizei - len)) && ((*buffer - bstart) < bufsize); + i++) { + **buffer = c; + *buffer += 1; + } + } + return 1; +} + +static int +print_str(char **buffer, size_t bufsize, const char *str) +{ + char *bstart = *buffer; + size_t i; + + for (i = 0; (i < strlen(str)) && ((*buffer - bstart) < bufsize); i++) { + **buffer = str[i]; + *buffer += 1; + } + return 1; +} + +static unsigned int __attrconst +print_intlen(unsigned long value, unsigned short int base) +{ + int i = 0; + + while (value > 0) { + if (base == 16) + value >>= 4; + else + value /= base; + i++; + } + if (i == 0) + i = 1; + return i; +} + +static int +print_itoa(char **buffer, size_t bufsize, unsigned long value, + unsigned short base, bool upper) +{ + const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + char c; + int i, len; + + if(base <= 2 || base > 16) + return 0; + + len = i = print_intlen(value, base); + + /* Don't print to buffer if bufsize is not enough. */ + if (len > bufsize) + return 0; + + do { + c = zeichen[value % base]; + if (upper) + c = toupper(c); + + (*buffer)[--i] = c; + value /= base; + } while(value); + + *buffer += len; + + return 1; +} + + + +static int +print_fill(char **buffer, size_t bufsize, char *sizec, unsigned long size, + unsigned short int base, char c, int optlen) +{ + int i, sizei, len; + char *bstart = *buffer; + + sizei = strtoul(sizec, NULL, 10); + len = print_intlen(size, base) + optlen; + if (sizei > len) { + for (i = 0; + (i < (sizei - len)) && ((*buffer - bstart) < bufsize); + i++) { + **buffer = c; + *buffer += 1; + } + } + + return 0; +} + + +static int +print_format(char **buffer, size_t bufsize, const char *format, void *var) +{ + char *start; + unsigned int i = 0, length_mod = sizeof(int); + unsigned long value = 0; + unsigned long signBit; + char *form, sizec[32]; + char sign = ' '; + bool upper = false; + + form = (char *) format; + start = *buffer; + + form++; + if(*form == '0' || *form == '.') { + sign = '0'; + form++; + } + + while ((*form != '\0') && ((*buffer - start) < bufsize)) { + switch(*form) { + case 'u': + case 'd': + case 'i': + sizec[i] = '\0'; + value = (unsigned long) var; + signBit = 0x1ULL << (length_mod * 8 - 1); + if ((*form != 'u') && (signBit & value)) { + **buffer = '-'; + *buffer += 1; + value = (-(unsigned long)value) & convert[length_mod]; + } + print_fill(buffer, bufsize - (*buffer - start), + sizec, value, 10, sign, 0); + print_itoa(buffer, bufsize - (*buffer - start), + value, 10, upper); + break; + case 'X': + upper = true; + /* fallthrough */ + case 'x': + sizec[i] = '\0'; + value = (unsigned long) var & convert[length_mod]; + print_fill(buffer, bufsize - (*buffer - start), + sizec, value, 16, sign, 0); + print_itoa(buffer, bufsize - (*buffer - start), + value, 16, upper); + break; + case 'O': + case 'o': + sizec[i] = '\0'; + value = (long int) var & convert[length_mod]; + print_fill(buffer, bufsize - (*buffer - start), + sizec, value, 8, sign, 0); + print_itoa(buffer, bufsize - (*buffer - start), + value, 8, upper); + break; + case 'p': + sizec[i] = '\0'; + print_fill(buffer, bufsize - (*buffer - start), + sizec, (unsigned long) var, 16, ' ', 2); + print_str(buffer, bufsize - (*buffer - start), + "0x"); + print_itoa(buffer, bufsize - (*buffer - start), + (unsigned long) var, 16, upper); + break; + case 'c': + sizec[i] = '\0'; + print_fill(buffer, bufsize - (*buffer - start), + sizec, 1, 10, ' ', 0); + **buffer = (unsigned long) var; + *buffer += 1; + break; + case 's': + sizec[i] = '\0'; + print_str_fill(buffer, + bufsize - (*buffer - start), sizec, + (char *) var, ' '); + + print_str(buffer, bufsize - (*buffer - start), + (char *) var); + break; + case 'l': + form++; + if(*form == 'l') { + length_mod = sizeof(long long int); + } else { + form--; + length_mod = sizeof(long int); + } + break; + case 'h': + form++; + if(*form == 'h') { + length_mod = sizeof(signed char); + } else { + form--; + length_mod = sizeof(short int); + } + break; + case 'z': + length_mod = sizeof(size_t); + break; + default: + if(*form >= '0' && *form <= '9') + sizec[i++] = *form; + } + form++; + } + + + return (long int) (*buffer - start); +} + + +/* + * The vsnprintf function prints a formatted strings into a buffer. + * BUG: buffer size checking does not fully work yet + */ +int +vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg) +{ + char *ptr, *bstart; + + bstart = buffer; + ptr = (char *) format; + + /* + * Return from here if size passed is zero, otherwise we would + * overrun buffer while setting NULL character at the end. + */ + if (!buffer || !bufsize) + return 0; + + /* Leave one space for NULL character */ + bufsize--; + + while(*ptr != '\0' && (buffer - bstart) < bufsize) + { + if(*ptr == '%') { + char formstr[20]; + int i=0; + + do { + formstr[i] = *ptr; + ptr++; + i++; + } while(!(*ptr == 'd' || *ptr == 'i' || *ptr == 'u' || *ptr == 'x' || *ptr == 'X' + || *ptr == 'p' || *ptr == 'c' || *ptr == 's' || *ptr == '%' + || *ptr == 'O' || *ptr == 'o' )); + formstr[i++] = *ptr; + formstr[i] = '\0'; + if(*ptr == '%') { + *buffer++ = '%'; + } else { + print_format(&buffer, + bufsize - (buffer - bstart), + formstr, va_arg(arg, void *)); + } + ptr++; + } else { + + *buffer = *ptr; + + buffer++; + ptr++; + } + } + + *buffer = '\0'; + + return (buffer - bstart); +} From 4e3cf62f5bdc481eeb31b7e1556442291925f3ae Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Sat, 9 May 2020 20:12:09 +0930 Subject: [PATCH 3/3] Add Linux loader This privdes just enough firmware to load Linux. The loader is linked to run from the aliased BRAM address. This means you should configure your SoC with BRAM (ie, don't pass --no_bram). It can load a raw kernel (vmlinux.bin) or a wrapper that embeds the device tree (dtbImage.microwatt). The printf comes from https://github.com/mpredfearn/simple-printf 1. Build Linux for microwatt objcopy -O binary microwatt/vmlinux vmlinux.bin 2. Build a dtb 3. Set MW_DEBUG to point to a copy of mw_debug and type `make load` to load the loader into BRAM. 4. Press 'RESET' 5. Follow the instructions: Microwatt Loader (Jun 22 2020 16:44:59 Load binaries into SDRAM and select option to start: vmlinux.bin and dtb: mw_debug -b jtag stop load vmlinux.bin load microwatt.dtb 0x1000000 start press 'l' to start' dtbImage.microwatt: mw_debug -b jtag stop load dtbImage.microwatt 0x500000 start press 'w' to start' Flash: To boot a binary from flash, write it to 0000000000300000 press 'f' to start' If you want to test other software, such as MicroPython, you can also load it to the start of SDRAM and the loader will jump to it with 'l'. Signed-off-by: Joel Stanley --- .gitignore | 9 +++ loader/Makefile | 64 +++++++++++++++++ loader/head.S | 38 ++++++++++ loader/loader.c | 161 +++++++++++++++++++++++++++++++++++++++++++ loader/powerpc.lds.S | 20 ++++++ 5 files changed, 292 insertions(+) create mode 100644 loader/Makefile create mode 100644 loader/head.S create mode 100644 loader/loader.c create mode 100644 loader/powerpc.lds.S diff --git a/.gitignore b/.gitignore index 3829b90..9afeb0a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.cf *.s *_tb +*.swp main_ram.bin tests/*/*.bin tests/*/*.hex @@ -10,3 +11,11 @@ tests/*/*.elf TAGS litedram/build/* obj_dir/* +tags +scripts/mw_debug/mw_debug +loader/loader.bin +loader/loader.hex +loader/loader.elf +loader/powerpc.lds +*.swn +*.swo diff --git a/loader/Makefile b/loader/Makefile new file mode 100644 index 0000000..f434e0e --- /dev/null +++ b/loader/Makefile @@ -0,0 +1,64 @@ +ARCH = $(shell uname -m) +ifneq ("$(ARCH)", "ppc64") +ifneq ("$(ARCH)", "ppc64le") + CROSS_COMPILE ?= powerpc64le-linux-gnu- +endif +endif + +PYTHON3 ?= python3 +MW_DEBUG ?= mw_debug +BRAM_ADDRESS ?= 0x80000000 + +# Use make V=1 for a verbose build. +ifndef V + Q_CC= @echo ' [CC] ' $@; + Q_LINK= @echo ' [LINK] ' $@; + Q_OBJCOPY=@echo ' [OBJCOPY] ' $@; + Q_PYTHON= @echo ' [PYTHON] ' $@; +endif + +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy + +CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple \ + -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector \ + -mstrict-align -ffreestanding -nostdinc -flto \ + -Ilibc/include/ -I../include -isystem $(shell $(CC) -print-file-name=include) \ + -D__USE_LIBC +ASFLAGS = $(CFLAGS) +LDFLAGS = -T powerpc.lds -static -nostdlib -Wl,--gc-sections -Wl,--build-id=none + +LIBC_SRC := libc/src/isdigit.c libc/src/memcmp.c libc/src/strcat.c \ + libc/src/strncasecmp.c libc/src/strtok.c libc/src/vsnprintf.c \ + libc/src/isprint.c libc/src/memcpy.c libc/src/strchr.c libc/src/strncmp.c \ + libc/src/strtol.c libc/src/isspace.c libc/src/memmove.c libc/src/strcmp.c \ + libc/src/strncpy.c libc/src/strtoul.c libc/src/isxdigit.c libc/src/memset.c \ + libc/src/strcpy.c libc/src/strrchr.c libc/src/tolower.c libc/src/memchr.c \ + libc/src/strcasecmp.c libc/src/strlen.c libc/src/strstr.c libc/src/toupper.c +LIBC_OBJ := $(LIBC_SRC:.c=.o) + +COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +COMPILE.S = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c + +all: loader.hex + +load: loader.bin + $(MW_DEBUG) -b jtag load $^ $(BRAM_ADDRESS) + +%.lds : %.lds.S + $(Q_CC)$(CC) -I../include -P -E $< -o $@ + +loader.elf: loader.o head.o ../lib/console.o $(LIBC_OBJ) | powerpc.lds + $(Q_LINK)$(CC) $(LDFLAGS) -o $@ $^ + @size $@ + +loader.bin: loader.elf + $(Q_OBJCOPY)$(OBJCOPY) -O binary $^ $@ + +loader.hex: loader.bin + $(Q_PYTHON)$(PYTHON3) ../scripts/bin2hex.py $^ > $@ + +.PHONY: +clean: + @rm -f *.o $(LIBC_OBJ) ../lib/console.o loader.elf loader.bin loader.hex powerpc.lds diff --git a/loader/head.S b/loader/head.S new file mode 100644 index 0000000..a141c20 --- /dev/null +++ b/loader/head.S @@ -0,0 +1,38 @@ +/* Copyright 2020 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define STACK_TOP (BRAM_BASE + 0x3000) + +/* Load an immediate 64-bit value into a register */ +#define LOAD_IMM64(r, e) \ + lis r,(e)@highest; \ + ori r,r,(e)@higher; \ + rldicr r,r, 32, 31; \ + oris r,r, (e)@h; \ + ori r,r, (e)@l; + + .section ".head","ax" + +.global start +start: + /* setup stack */ + LOAD_IMM64(%r1, STACK_TOP - 0x100) + LOAD_IMM64(%r12, main) + mtctr %r12, + bctrl + b . diff --git a/loader/loader.c b/loader/loader.c new file mode 100644 index 0000000..d8725c6 --- /dev/null +++ b/loader/loader.c @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include "stdio.h" + +#include "io.h" +#include "microwatt_soc.h" +#include "console.h" +#include "elf64.h" + +#define DTB_ADDR 0x01000000UL +#define DTBIMAGE_ADDR 0x00500000UL + +#ifdef DEBUG +#define debug(...) printf(__VA_ARGS__) +#else +#define debug(...) do {} while(0) +#endif + +int _printf(const char *fmt, ...) +{ + int count; + char buffer[128]; + va_list ap; + + va_start(ap, fmt); + count = vsnprintf(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + puts(buffer); + return count; +} + +static inline void flush_cpu_icache(void) +{ + __asm__ volatile ("icbi 0,0; isync" : : : "memory"); +} + +static void print_hex(unsigned long val) +{ + int i, nibbles = sizeof(val)*2; + char buf[sizeof(val)*2+1]; + + for (i = nibbles-1; i >= 0; i--) { + buf[i] = (val & 0xf) + '0'; + if (buf[i] > '9') + buf[i] += ('a'-'0'-10); + val >>= 4; + } + buf[nibbles] = '\0'; + puts(buf); +} + +static void fl_read(void *dst, uint32_t offset, uint32_t size) +{ + memcpy(dst, (void *)(unsigned long)(SPI_FLASH_BASE + offset), size); +} + +static unsigned long boot_flash(unsigned int offset) +{ + Elf64_Ehdr ehdr; + Elf64_Phdr ph; + unsigned int i, poff, size, off; + void *addr; + + fl_read(&ehdr, offset, sizeof(ehdr)); + if (!IS_ELF(ehdr) || ehdr.e_ident[EI_CLASS] != ELFCLASS64) { + puts("Doesn't look like an elf64\n"); + return -1UL; + } + if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB || + ehdr.e_machine != EM_PPC64) { + puts("Not a ppc64le binary\n"); + return -1UL; + } + + poff = offset + ehdr.e_phoff; + for (i = 0; i < ehdr.e_phnum; i++) { + fl_read(&ph, poff, sizeof(ph)); + if (ph.p_type != PT_LOAD) + continue; + + /* XXX Add bound checking ! */ + size = ph.p_filesz; + addr = (void *)ph.p_vaddr; + off = offset + ph.p_offset; + debug("Copy segment %d (0x%x bytes) to %p\n", i, size, addr); + fl_read(addr, off, size); + poff += ehdr.e_phentsize; + } + + if (poff == offset + ehdr.e_phoff) { + puts("Did not find any loadable sections\n"); + return -1UL; + } + + debug("Found entry point: %x\n", ehdr.e_entry); + + flush_cpu_icache(); + return ehdr.e_entry; +} + +int main(void) +{ + unsigned long fl_off = 0; + potato_uart_init(); + unsigned long payload, dtb; + void __attribute__((noreturn)) (*enter_kernel)(unsigned long fdt, + unsigned long entry, + unsigned long of); + + + puts("\nMicrowatt Loader ("__DATE__" "__TIME__"\n\n"); + + writeq(SYS_REG_CTRL_DRAM_AT_0, SYSCON_BASE + SYS_REG_CTRL); + flush_cpu_icache(); + + puts("Load binaries into SDRAM and select option to start:\n\n"); + puts("vmlinux.bin and dtb:\n"); + puts(" mw_debug -b jtag stop load vmlinux.bin load microwatt.dtb 0x1000000 start\n"); + puts(" press 'l' to start'\n\n"); + + puts("dtbImage.microwatt:\n"); + puts(" mw_debug -b jtag stop load dtbImage.microwatt 0x500000 start\n"); + puts(" press 'w' to start'\n\n"); + + if (readq(SYSCON_BASE + SYS_REG_INFO) & SYS_REG_INFO_HAS_SPI_FLASH) { + unsigned long val = readq(SYSCON_BASE + SYS_REG_SPI_INFO); + fl_off = val & SYS_REG_SPI_INFO_FLASH_OFF_MASK; + + puts("Flash:\n"); + puts(" To boot a binary from flash, write it to "); print_hex(fl_off); puts("\n"); + puts(" press 'f' to start'\n\n"); + } + + while (1) { + switch (getchar()) { + case 'l': + payload = 0; + dtb = DTB_ADDR; + goto load; + case 'w': + payload = DTBIMAGE_ADDR; + goto load; + case 'f': + payload = boot_flash(fl_off); + if (payload == -1UL) + continue; + goto load; + default: + continue; + } + } + +load: + puts("Entering payload at "); print_hex(payload); puts("...\n"); + + enter_kernel = (void *)payload; + + enter_kernel(dtb, 0, 0); +} diff --git a/loader/powerpc.lds.S b/loader/powerpc.lds.S new file mode 100644 index 0000000..8b08d62 --- /dev/null +++ b/loader/powerpc.lds.S @@ -0,0 +1,20 @@ +#include + +#define BASE_ADDR BRAM_BASE + +SECTIONS +{ + . = BASE_ADDR; + .head : { + KEEP(*(.head)) + } + + .text : { *(.text*) *(.sfpr) *(.rodata*) } + .data : { *(.data*) } + .bss : { *(.bss*) } + + /DISCARD/ : { + *(.note.*) + *(.comment) + } +}