aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/libc
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/libc')
-rw-r--r--roms/skiboot/libc/Makefile.inc11
-rw-r--r--roms/skiboot/libc/README.txt62
-rw-r--r--roms/skiboot/libc/ctype/Makefile.inc19
-rw-r--r--roms/skiboot/libc/ctype/isdigit.c26
-rw-r--r--roms/skiboot/libc/ctype/isprint.c19
-rw-r--r--roms/skiboot/libc/ctype/isspace.c30
-rw-r--r--roms/skiboot/libc/ctype/isxdigit.c22
-rw-r--r--roms/skiboot/libc/ctype/tolower.c19
-rw-r--r--roms/skiboot/libc/ctype/toupper.c21
-rw-r--r--roms/skiboot/libc/include/assert.h60
-rw-r--r--roms/skiboot/libc/include/ctype.h26
-rw-r--r--roms/skiboot/libc/include/errno.h36
-rw-r--r--roms/skiboot/libc/include/getopt.h37
-rw-r--r--roms/skiboot/libc/include/limits.h36
-rw-r--r--roms/skiboot/libc/include/stdint.h30
-rw-r--r--roms/skiboot/libc/include/stdio.h72
-rw-r--r--roms/skiboot/libc/include/stdlib.h31
-rw-r--r--roms/skiboot/libc/include/string.h52
-rw-r--r--roms/skiboot/libc/include/time.h39
-rw-r--r--roms/skiboot/libc/include/unistd.h26
-rw-r--r--roms/skiboot/libc/stdio/Makefile.inc21
-rw-r--r--roms/skiboot/libc/stdio/fileno.c19
-rw-r--r--roms/skiboot/libc/stdio/fprintf.c26
-rw-r--r--roms/skiboot/libc/stdio/fputc.c24
-rw-r--r--roms/skiboot/libc/stdio/fputs.c23
-rw-r--r--roms/skiboot/libc/stdio/putchar.c21
-rw-r--r--roms/skiboot/libc/stdio/puts.c27
-rw-r--r--roms/skiboot/libc/stdio/setvbuf.c28
-rw-r--r--roms/skiboot/libc/stdio/snprintf.c30
-rw-r--r--roms/skiboot/libc/stdio/stdchnls.c23
-rw-r--r--roms/skiboot/libc/stdio/vfprintf.c27
-rw-r--r--roms/skiboot/libc/stdio/vsnprintf.c300
-rw-r--r--roms/skiboot/libc/stdlib/Makefile.inc20
-rw-r--r--roms/skiboot/libc/stdlib/atoi.c18
-rw-r--r--roms/skiboot/libc/stdlib/atol.c18
-rw-r--r--roms/skiboot/libc/stdlib/error.c16
-rw-r--r--roms/skiboot/libc/stdlib/labs.c25
-rw-r--r--roms/skiboot/libc/stdlib/rand.c24
-rw-r--r--roms/skiboot/libc/stdlib/strtol.c113
-rw-r--r--roms/skiboot/libc/stdlib/strtoul.c103
-rw-r--r--roms/skiboot/libc/string/Makefile.inc23
-rw-r--r--roms/skiboot/libc/string/memchr.c28
-rw-r--r--roms/skiboot/libc/string/memcmp.c29
-rw-r--r--roms/skiboot/libc/string/memcpy.c36
-rw-r--r--roms/skiboot/libc/string/memcpy_from_ci.c41
-rw-r--r--roms/skiboot/libc/string/memmove.c36
-rw-r--r--roms/skiboot/libc/string/memset.c54
-rw-r--r--roms/skiboot/libc/string/strcasecmp.c27
-rw-r--r--roms/skiboot/libc/string/strcat.c26
-rw-r--r--roms/skiboot/libc/string/strchr.c28
-rw-r--r--roms/skiboot/libc/string/strcmp.c25
-rw-r--r--roms/skiboot/libc/string/strcpy.c23
-rw-r--r--roms/skiboot/libc/string/strdup.c27
-rw-r--r--roms/skiboot/libc/string/strlen.c40
-rw-r--r--roms/skiboot/libc/string/strncasecmp.c30
-rw-r--r--roms/skiboot/libc/string/strncmp.c30
-rw-r--r--roms/skiboot/libc/string/strncpy.c33
-rw-r--r--roms/skiboot/libc/string/strrchr.c28
-rw-r--r--roms/skiboot/libc/string/strstr.c39
-rw-r--r--roms/skiboot/libc/string/strtok.c48
-rw-r--r--roms/skiboot/libc/test/.gitignore10
-rw-r--r--roms/skiboot/libc/test/Makefile.check74
-rw-r--r--roms/skiboot/libc/test/run-ctype-test.c56
-rw-r--r--roms/skiboot/libc/test/run-ctype.c95
-rw-r--r--roms/skiboot/libc/test/run-memops-test.c97
-rw-r--r--roms/skiboot/libc/test/run-memops.c98
-rw-r--r--roms/skiboot/libc/test/run-snprintf-test.c42
-rw-r--r--roms/skiboot/libc/test/run-snprintf.c246
-rw-r--r--roms/skiboot/libc/test/run-stdlib-test.c19
-rw-r--r--roms/skiboot/libc/test/run-stdlib.c85
-rw-r--r--roms/skiboot/libc/test/run-time.c86
-rw-r--r--roms/skiboot/libc/time.c142
72 files changed, 3281 insertions, 0 deletions
diff --git a/roms/skiboot/libc/Makefile.inc b/roms/skiboot/libc/Makefile.inc
new file mode 100644
index 000000000..13f8034f4
--- /dev/null
+++ b/roms/skiboot/libc/Makefile.inc
@@ -0,0 +1,11 @@
+LIBCDIR = libc
+
+SUBDIRS += $(LIBCDIR)
+LIBC = $(LIBCDIR)/built-in.a $(LIBCDIR)/time.o
+
+include $(SRC)/$(LIBCDIR)/string/Makefile.inc
+include $(SRC)/$(LIBCDIR)/ctype/Makefile.inc
+include $(SRC)/$(LIBCDIR)/stdlib/Makefile.inc
+include $(SRC)/$(LIBCDIR)/stdio/Makefile.inc
+
+$(LIBC): $(STRING) $(CTYPE) $(STDLIB) $(STDIO)
diff --git a/roms/skiboot/libc/README.txt b/roms/skiboot/libc/README.txt
new file mode 100644
index 000000000..d6c3eb2c1
--- /dev/null
+++ b/roms/skiboot/libc/README.txt
@@ -0,0 +1,62 @@
+
+skiboot changes:
+
+ - Added malloc lock
+ - Added a few functions
+ - Malloc will always 4 byte align everything
+ - Added asserts, requires core to provide abort()
+
+WARNINGS:
+
+ - don't use free() on the result of memalign() (should be fixable)
+
+Previous notes:
+
+ Standard C library for the SLOF firmware project
+ ================================================
+
+To use this library, link your target against the "libc.a" archive.
+
+However, there are some prerequisites before you can use certain parts of the
+library:
+
+1) If you want to use malloc() and the like, you have to supply an implemen-
+ tation of sbrk() in your own code. malloc() uses sbrk() to get new, free
+ memory regions.
+
+ Prototype: void *sbrk(int incr);
+ Description: sbrk() increments the available data space by incr bytes and
+ returns a pointer to the start of the new area.
+
+ See the man-page of sbrk for details about this function.
+
+2) Before you can use the stdio output functions like printf(), puts() and the
+ like, you have to provide a standard write() function in your code.
+ printf() and the like use write() to print out the strings to the standard
+ output.
+
+ Prototype: ssize_t write(int fd, const void *buf, size_t cnt);
+ Description: Write cnt byte from the buffer buf to the stream associated
+ with the file descriptor fd.
+
+ The stdio functions will print their output to the stdout channel which is
+ assigned with the file descriptor 1 by default. Note that the stdio
+ functions will not use open() before calling write(), so if the stdout
+ cannel needs to be opened first, you should do that in your start-up code
+ before using the libc functions for the first time.
+
+3) Before you can use the stdio input functions like scanf() and the
+ like, you have to provide a standard read() function in your code.
+ scanf() and the like use read() to get the characters from the standard
+ input.
+
+ Prototype: ssize_t read(int fd, void *buf, size_t cnt);
+ Description: Read cnt byte from the stream associated with the file
+ descriptor fd and put them into the buffer buf.
+
+ The stdio functions will get their input from the stdin channel which is
+ assigned with the file descriptor 0 by default. Note that the stdio
+ functions will not use open() before calling read(), so if the stdin
+ cannel needs to be opened first, you should do that in your start-up code
+ before using the libc functions for the first time.
+
diff --git a/roms/skiboot/libc/ctype/Makefile.inc b/roms/skiboot/libc/ctype/Makefile.inc
new file mode 100644
index 000000000..c183a54b8
--- /dev/null
+++ b/roms/skiboot/libc/ctype/Makefile.inc
@@ -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
+# ****************************************************************************/
+
+SUBDIRS += $(LIBCDIR)/ctype
+
+CTYPE_OBJS = isdigit.o isprint.o isspace.o isxdigit.o tolower.o toupper.o
+
+CTYPE = $(LIBCDIR)/ctype/built-in.a
+$(CTYPE): $(CTYPE_OBJS:%=$(LIBCDIR)/ctype/%)
+
diff --git a/roms/skiboot/libc/ctype/isdigit.c b/roms/skiboot/libc/ctype/isdigit.c
new file mode 100644
index 000000000..68cd4eb79
--- /dev/null
+++ b/roms/skiboot/libc/ctype/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 <compiler.h>
+#include <ctype.h>
+
+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/roms/skiboot/libc/ctype/isprint.c b/roms/skiboot/libc/ctype/isprint.c
new file mode 100644
index 000000000..0a7c94ce8
--- /dev/null
+++ b/roms/skiboot/libc/ctype/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 <compiler.h>
+#include <ctype.h>
+
+int __attrconst isprint(int ch)
+{
+ return (ch >= 32 && ch < 127);
+}
diff --git a/roms/skiboot/libc/ctype/isspace.c b/roms/skiboot/libc/ctype/isspace.c
new file mode 100644
index 000000000..f9fa36a3a
--- /dev/null
+++ b/roms/skiboot/libc/ctype/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 <compiler.h>
+#include <ctype.h>
+
+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/roms/skiboot/libc/ctype/isxdigit.c b/roms/skiboot/libc/ctype/isxdigit.c
new file mode 100644
index 000000000..d3c73888e
--- /dev/null
+++ b/roms/skiboot/libc/ctype/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 <compiler.h>
+#include <ctype.h>
+
+int __attrconst isxdigit(int ch)
+{
+ return (
+ (ch >= '0' && ch <= '9') |
+ (ch >= 'A' && ch <= 'F') |
+ (ch >= 'a' && ch <= 'f') );
+}
diff --git a/roms/skiboot/libc/ctype/tolower.c b/roms/skiboot/libc/ctype/tolower.c
new file mode 100644
index 000000000..398a1eb29
--- /dev/null
+++ b/roms/skiboot/libc/ctype/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 <compiler.h>
+#include <ctype.h>
+
+int __attrconst tolower(int c)
+{
+ return (((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a' ) : c);
+}
diff --git a/roms/skiboot/libc/ctype/toupper.c b/roms/skiboot/libc/ctype/toupper.c
new file mode 100644
index 000000000..6b52363d1
--- /dev/null
+++ b/roms/skiboot/libc/ctype/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 <compiler.h>
+#include "ctype.h"
+
+int __attrconst toupper (int cha)
+{
+ if((cha >= 'a') && (cha <= 'z'))
+ return(cha - 'a' + 'A');
+ return(cha);
+}
diff --git a/roms/skiboot/libc/include/assert.h b/roms/skiboot/libc/include/assert.h
new file mode 100644
index 000000000..1e511fbe5
--- /dev/null
+++ b/roms/skiboot/libc/include/assert.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * 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
+
+struct trap_table_entry {
+ unsigned long address;
+ const char *message;
+};
+
+extern struct trap_table_entry __trap_table_start[];
+extern struct trap_table_entry __trap_table_end[];
+
+#define stringify(expr) stringify_1(expr)
+/* Double-indirection required to stringify expansions */
+#define stringify_1(expr) #expr
+
+void __attribute__((noreturn)) assert_fail(const char *msg,
+ const char *file,
+ unsigned int line,
+ const char *function);
+
+/*
+ * The 'nop' gets patched to 'trap' after skiboot takes over the exception
+ * vectors, then patched to 'nop' before booting the OS (see patch_traps).
+ * This makes assert fall through to assert_fail when we can't use the 0x700
+ * interrupt.
+ */
+#define assert(cond) \
+do { \
+ /* evaluate cond exactly once */ \
+ const unsigned long __cond = (unsigned long)(cond); \
+ asm volatile( \
+ " cmpdi %0,0" "\n\t" \
+ " bne 2f" "\n\t" \
+ "1: nop # assert" "\n\t" \
+ "2:" "\n\t" \
+ ".section .rodata" "\n\t" \
+ "3: .string \"assert failed at " __FILE__ ":" stringify(__LINE__) "\"" "\n\t" \
+ ".previous" "\n\t" \
+ ".section .trap_table,\"aw\"" "\n\t" \
+ ".llong 1b" "\n\t" \
+ ".llong 3b" "\n\t" \
+ ".previous" "\n\t" \
+ : : "r"(__cond) : "cr0"); \
+ if (!__cond) \
+ assert_fail(stringify(cond), __FILE__, __LINE__, __FUNCTION__); \
+} while (0)
+
+#endif
diff --git a/roms/skiboot/libc/include/ctype.h b/roms/skiboot/libc/include/ctype.h
new file mode 100644
index 000000000..60c98b059
--- /dev/null
+++ b/roms/skiboot/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 <compiler.h>
+
+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/roms/skiboot/libc/include/errno.h b/roms/skiboot/libc/include/errno.h
new file mode 100644
index 000000000..c2bd98774
--- /dev/null
+++ b/roms/skiboot/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/roms/skiboot/libc/include/getopt.h b/roms/skiboot/libc/include/getopt.h
new file mode 100644
index 000000000..5956986a5
--- /dev/null
+++ b/roms/skiboot/libc/include/getopt.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * 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 GETOPT_H
+#define GETOPT_H
+
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+
+struct option {
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+enum {
+ no_argument = 0,
+ required_argument,
+ optional_argument
+};
+
+int getopt(int argc, char **, const char *);
+int getopt_long(int argc, char **, const char *, const struct option *, int *);
+
+#endif /* GETOPT_H */
diff --git a/roms/skiboot/libc/include/limits.h b/roms/skiboot/libc/include/limits.h
new file mode 100644
index 000000000..bd67c7ecc
--- /dev/null
+++ b/roms/skiboot/libc/include/limits.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 _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)
+
+#define CHAR_BIT 8
+
+#define UINT32_MAX UINT_MAX
+
+#endif
diff --git a/roms/skiboot/libc/include/stdint.h b/roms/skiboot/libc/include/stdint.h
new file mode 100644
index 000000000..2a2c1d916
--- /dev/null
+++ b/roms/skiboot/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/roms/skiboot/libc/include/stdio.h b/roms/skiboot/libc/include/stdio.h
new file mode 100644
index 000000000..5dc4502b0
--- /dev/null
+++ b/roms/skiboot/libc/include/stdio.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * 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 <stdarg.h>
+#include "stddef.h"
+
+#define EOF (-1)
+
+#define _IONBF 0
+#define _IOLBF 1
+#define _IOFBF 2
+#define BUFSIZ 80
+
+typedef struct {
+ int fd;
+ int mode;
+ int pos;
+ char *buf;
+ int bufsiz;
+} FILE;
+
+extern FILE stdin_data;
+extern FILE stdout_data;
+extern FILE stderr_data;
+
+#define stdin (&stdin_data)
+#define stdout (&stdout_data)
+#define stderr (&stderr_data)
+
+int fileno(FILE *stream);
+
+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 fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3)));
+int snprintf(char *str, size_t size, const char *format, ...) __attribute__((format (printf, 3, 4)));
+int vfprintf(FILE *stream, const char *format, va_list);
+int vsnprintf(char *str, size_t size, const char *format, va_list);
+void setbuf(FILE *stream, char *buf);
+int setvbuf(FILE *stream, char *buf, int mode , size_t size);
+
+int fputc(int ch, FILE *stream);
+#define putc(ch, stream) fputc(ch, stream)
+int putchar(int ch);
+int puts(const char *str);
+int fputs(const char *str, FILE *stream);
+
+int scanf(const char *format, ...) __attribute__((format (scanf, 1, 2)));
+int fscanf(FILE *stream, const char *format, ...) __attribute__((format (scanf, 2, 3)));
+int vfscanf(FILE *stream, const char *format, va_list);
+int vsscanf(const char *str, const char *format, va_list);
+int getc(FILE *stream);
+int getchar(void);
+
+#endif
diff --git a/roms/skiboot/libc/include/stdlib.h b/roms/skiboot/libc/include/stdlib.h
new file mode 100644
index 000000000..43d5c24dd
--- /dev/null
+++ b/roms/skiboot/libc/include/stdlib.h
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * 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
+
+#include "mem_region-malloc.h"
+
+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);
+
+int rand(void);
+long int __attribute__((const)) labs(long int n);
+#define abort() assert(0)
+
+#endif
diff --git a/roms/skiboot/libc/include/string.h b/roms/skiboot/libc/include/string.h
new file mode 100644
index 000000000..f3d6117fb
--- /dev/null
+++ b/roms/skiboot/libc/include/string.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ * 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"
+
+#define strcpy __builtin_strcpy
+#define strncpy __builtin_strncpy
+#define strcat __builtin_strcat
+#define strcmp __builtin_strcmp
+#define strncmp __builtin_strncmp
+#define strcasecmp __builtin_strcasecmp
+#define strncasecmp __builtin_strncasecmp
+#define strchr __builtin_strchr
+#define strrchr __builtin_strrchr
+#define strlen __builtin_strlen
+#define strlen __builtin_strlen
+size_t strnlen(const char *s, size_t maxlen);
+#define strstr __builtin_strstr
+#define strdup __builtin_strdup
+char *strtok(char *src, const char *pattern);
+
+#define memset __builtin_memset
+#define memchr __builtin_memchr
+#define memcpy __builtin_memcpy
+#define memmove __builtin_memmove
+#define memcmp __builtin_memcmp
+static inline void *memcpy_null(void *dest, const void *src, size_t n)
+{
+ asm("" : "+r"(dest));
+ asm("" : "+r"(src));
+ return memcpy(dest, src, n);
+}
+void *memcpy_from_ci(void *destpp, const void *srcpp, size_t len);
+
+static inline int ffs(unsigned long val)
+{
+ return __builtin_ffs(val);
+}
+
+#endif
diff --git a/roms/skiboot/libc/include/time.h b/roms/skiboot/libc/include/time.h
new file mode 100644
index 000000000..8d34fdbab
--- /dev/null
+++ b/roms/skiboot/libc/include/time.h
@@ -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
+ *****************************************************************************/
+#ifndef _TIME_H
+#define _TIME_H
+
+struct tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+};
+
+typedef long time_t;
+
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+
+struct tm *gmtime_r(const time_t *timep, struct tm *result);
+time_t mktime(struct tm *tm);
+
+/* Not implemented by libc but by hosting environment, however
+ * this is where the prototype is expected
+ */
+int nanosleep(const struct timespec *req, struct timespec *rem);
+
+#endif /* _TIME_H */
diff --git a/roms/skiboot/libc/include/unistd.h b/roms/skiboot/libc/include/unistd.h
new file mode 100644
index 000000000..bc53472dc
--- /dev/null
+++ b/roms/skiboot/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 <stddef.h>
+
+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/roms/skiboot/libc/stdio/Makefile.inc b/roms/skiboot/libc/stdio/Makefile.inc
new file mode 100644
index 000000000..a5436d734
--- /dev/null
+++ b/roms/skiboot/libc/stdio/Makefile.inc
@@ -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
+# ****************************************************************************/
+
+
+SUBDIRS += $(LIBCDIR)/stdio
+
+STDIO_OBJS = vfprintf.o vsnprintf.o fprintf.o \
+ setvbuf.o fputc.o puts.o fputs.o putchar.o \
+ stdchnls.o fileno.o snprintf.o
+
+STDIO = $(LIBCDIR)/stdio/built-in.a
+$(STDIO): $(STDIO_OBJS:%=$(LIBCDIR)/stdio/%)
diff --git a/roms/skiboot/libc/stdio/fileno.c b/roms/skiboot/libc/stdio/fileno.c
new file mode 100644
index 000000000..6e239511d
--- /dev/null
+++ b/roms/skiboot/libc/stdio/fileno.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 <stdio.h>
+
+int
+fileno(FILE *stream)
+{
+ return stream->fd;
+}
diff --git a/roms/skiboot/libc/stdio/fprintf.c b/roms/skiboot/libc/stdio/fprintf.c
new file mode 100644
index 000000000..866df3934
--- /dev/null
+++ b/roms/skiboot/libc/stdio/fprintf.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 "stdio.h"
+
+
+int fprintf(FILE *stream, const char* fmt, ...)
+{
+ int count;
+ va_list ap;
+
+ va_start(ap, fmt);
+ count = vfprintf(stream, fmt, ap);
+ va_end(ap);
+
+ return count;
+}
diff --git a/roms/skiboot/libc/stdio/fputc.c b/roms/skiboot/libc/stdio/fputc.c
new file mode 100644
index 000000000..6e9e7c9c0
--- /dev/null
+++ b/roms/skiboot/libc/stdio/fputc.c
@@ -0,0 +1,24 @@
+/******************************************************************************
+ * 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 "stdio.h"
+#include "unistd.h"
+
+int fputc(int ch, FILE *stream)
+{
+ unsigned char outchar = ch;
+
+ if (write(stream->fd, &outchar, 1) == 1)
+ return outchar;
+ else
+ return EOF;
+}
diff --git a/roms/skiboot/libc/stdio/fputs.c b/roms/skiboot/libc/stdio/fputs.c
new file mode 100644
index 000000000..c22329c9c
--- /dev/null
+++ b/roms/skiboot/libc/stdio/fputs.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
+ *****************************************************************************/
+
+
+#include "stdio.h"
+#include "string.h"
+#include "unistd.h"
+
+
+int fputs(const char *str, FILE *stream)
+{
+ return write(stream->fd, str, strlen(str));
+}
+
diff --git a/roms/skiboot/libc/stdio/putchar.c b/roms/skiboot/libc/stdio/putchar.c
new file mode 100644
index 000000000..5c750d90a
--- /dev/null
+++ b/roms/skiboot/libc/stdio/putchar.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 "stdio.h"
+
+
+int
+putchar(int ch)
+{
+ return putc(ch, stdout);
+}
diff --git a/roms/skiboot/libc/stdio/puts.c b/roms/skiboot/libc/stdio/puts.c
new file mode 100644
index 000000000..85d9d3109
--- /dev/null
+++ b/roms/skiboot/libc/stdio/puts.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 "stdio.h"
+#include "string.h"
+#include "unistd.h"
+
+
+int puts(const char *str)
+{
+ int ret;
+
+ ret = write(stdout->fd, str, strlen(str));
+ write(stdout->fd, "\n", 1);
+
+ return ret + 1;
+}
diff --git a/roms/skiboot/libc/stdio/setvbuf.c b/roms/skiboot/libc/stdio/setvbuf.c
new file mode 100644
index 000000000..9b62dd8ff
--- /dev/null
+++ b/roms/skiboot/libc/stdio/setvbuf.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 <stdio.h>
+
+int setvbuf(FILE *stream, char *buf, int mode , size_t size)
+{
+ if (mode != _IONBF && mode != _IOLBF && mode != _IOFBF)
+ return -1;
+ stream->buf = buf;
+ stream->mode = mode;
+ stream->bufsiz = size;
+ return 0;
+}
+
+void setbuf(FILE *stream, char *buf)
+{
+ setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
diff --git a/roms/skiboot/libc/stdio/snprintf.c b/roms/skiboot/libc/stdio/snprintf.c
new file mode 100644
index 000000000..35b6f86ca
--- /dev/null
+++ b/roms/skiboot/libc/stdio/snprintf.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 <stdio.h>
+
+
+int snprintf(char *buff, size_t size, const char *format, ...)
+{
+ va_list ar;
+ int count;
+
+ if (buff==NULL)
+ return(-1);
+
+ va_start(ar, format);
+ count = vsnprintf(buff, size, format, ar);
+ va_end(ar);
+
+ return(count);
+}
+
diff --git a/roms/skiboot/libc/stdio/stdchnls.c b/roms/skiboot/libc/stdio/stdchnls.c
new file mode 100644
index 000000000..41ed958bf
--- /dev/null
+++ b/roms/skiboot/libc/stdio/stdchnls.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
+ *****************************************************************************/
+
+
+#include "stdio.h"
+
+static char stdin_buffer[BUFSIZ], stdout_buffer[BUFSIZ];
+
+FILE stdin_data = { .fd = 0, .mode = _IOLBF, .pos = 0,
+ .buf = stdin_buffer, .bufsiz = BUFSIZ };
+FILE stdout_data = { .fd = 1, .mode = _IOLBF, .pos = 0,
+ .buf = stdout_buffer, .bufsiz = BUFSIZ };
+FILE stderr_data = { .fd = 2, .mode = _IONBF, .pos = 0,
+ .buf = NULL, .bufsiz = 0 };
diff --git a/roms/skiboot/libc/stdio/vfprintf.c b/roms/skiboot/libc/stdio/vfprintf.c
new file mode 100644
index 000000000..765feeace
--- /dev/null
+++ b/roms/skiboot/libc/stdio/vfprintf.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 "stdio.h"
+#include "unistd.h"
+
+
+int vfprintf(FILE *stream, const char *fmt, va_list ap)
+{
+ int count;
+ char buffer[320];
+
+ count = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ write(stream->fd, buffer, count);
+
+ return count;
+}
+
diff --git a/roms/skiboot/libc/stdio/vsnprintf.c b/roms/skiboot/libc/stdio/vsnprintf.c
new file mode 100644
index 000000000..410a806cb
--- /dev/null
+++ b/roms/skiboot/libc/stdio/vsnprintf.c
@@ -0,0 +1,300 @@
+/******************************************************************************
+ * 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 <stdbool.h>
+#include <compiler.h>
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+#include "ctype.h"
+
+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) {
+ 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);
+}
diff --git a/roms/skiboot/libc/stdlib/Makefile.inc b/roms/skiboot/libc/stdlib/Makefile.inc
new file mode 100644
index 000000000..8a78d173c
--- /dev/null
+++ b/roms/skiboot/libc/stdlib/Makefile.inc
@@ -0,0 +1,20 @@
+# *****************************************************************************
+# * 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
+# ****************************************************************************/
+
+SUBDIRS += $(LIBCDIR)/stdlib
+
+STDLIB_OBJS = error.o atoi.o atol.o strtol.o strtoul.o \
+ rand.o labs.o
+
+STDLIB = $(LIBCDIR)/stdlib/built-in.a
+$(STDLIB): $(STDLIB_OBJS:%=$(LIBCDIR)/stdlib/%)
+
diff --git a/roms/skiboot/libc/stdlib/atoi.c b/roms/skiboot/libc/stdlib/atoi.c
new file mode 100644
index 000000000..444c05a10
--- /dev/null
+++ b/roms/skiboot/libc/stdlib/atoi.c
@@ -0,0 +1,18 @@
+/******************************************************************************
+ * 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 <stdlib.h>
+
+int atoi(const char *str)
+{
+ return strtol(str, NULL, 10);
+}
diff --git a/roms/skiboot/libc/stdlib/atol.c b/roms/skiboot/libc/stdlib/atol.c
new file mode 100644
index 000000000..e73c7d476
--- /dev/null
+++ b/roms/skiboot/libc/stdlib/atol.c
@@ -0,0 +1,18 @@
+/******************************************************************************
+ * 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 <stdlib.h>
+
+long atol(const char *str)
+{
+ return strtol(str, NULL, 10);
+}
diff --git a/roms/skiboot/libc/stdlib/error.c b/roms/skiboot/libc/stdlib/error.c
new file mode 100644
index 000000000..1bec91b5d
--- /dev/null
+++ b/roms/skiboot/libc/stdlib/error.c
@@ -0,0 +1,16 @@
+/******************************************************************************
+ * 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 <errno.h>
+
+int errno;
+
diff --git a/roms/skiboot/libc/stdlib/labs.c b/roms/skiboot/libc/stdlib/labs.c
new file mode 100644
index 000000000..8bd15eab9
--- /dev/null
+++ b/roms/skiboot/libc/stdlib/labs.c
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Copyright (c) 2017 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 <stdlib.h>
+
+/**
+ * labs() - Computes the absolute value of long integer
+ * @n: long integer number
+ *
+ * Returns the absolute value of the long integer argument
+ */
+
+long int __attribute__((const)) labs(long int n)
+{
+ return (n > 0) ? n : -n;
+}
diff --git a/roms/skiboot/libc/stdlib/rand.c b/roms/skiboot/libc/stdlib/rand.c
new file mode 100644
index 000000000..e11702aa4
--- /dev/null
+++ b/roms/skiboot/libc/stdlib/rand.c
@@ -0,0 +1,24 @@
+/******************************************************************************
+ * 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 <stdlib.h>
+
+
+static unsigned long _rand = 1;
+
+int
+rand(void)
+{
+ _rand = _rand * 25364735 + 34563;
+
+ return ((unsigned int) (_rand >> 16) & RAND_MAX);
+}
diff --git a/roms/skiboot/libc/stdlib/strtol.c b/roms/skiboot/libc/stdlib/strtol.c
new file mode 100644
index 000000000..c7c52af01
--- /dev/null
+++ b/roms/skiboot/libc/stdlib/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 <stdlib.h>
+
+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/roms/skiboot/libc/stdlib/strtoul.c b/roms/skiboot/libc/stdlib/strtoul.c
new file mode 100644
index 000000000..e6e63aee7
--- /dev/null
+++ b/roms/skiboot/libc/stdlib/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 <stdlib.h>
+
+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/roms/skiboot/libc/string/Makefile.inc b/roms/skiboot/libc/string/Makefile.inc
new file mode 100644
index 000000000..2f038219f
--- /dev/null
+++ b/roms/skiboot/libc/string/Makefile.inc
@@ -0,0 +1,23 @@
+# *****************************************************************************
+# * 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
+# ****************************************************************************/
+
+SUBDIRS += $(LIBCDIR)/string
+
+STRING_OBJS = strcat.o strchr.o strrchr.o strcmp.o strcpy.o strlen.o \
+ strncmp.o strncpy.o strstr.o memset.o memcpy.o memcpy_from_ci.o \
+ memmove.o memchr.o memcmp.o strcasecmp.o strncasecmp.o \
+ strtok.o strdup.o
+STRING = $(LIBCDIR)/string/built-in.a
+$(STRING): $(STRING_OBJS:%=$(LIBCDIR)/string/%)
+
+CFLAGS_SKIP_libc/string/ += -Os
+CFLAGS_libc/string/ += -O2
diff --git a/roms/skiboot/libc/string/memchr.c b/roms/skiboot/libc/string/memchr.c
new file mode 100644
index 000000000..db9a147c6
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/memcmp.c b/roms/skiboot/libc/string/memcmp.c
new file mode 100644
index 000000000..b270b597b
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/memcpy.c b/roms/skiboot/libc/string/memcpy.c
new file mode 100644
index 000000000..26f953d2e
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+#include <ccan/short_types/short_types.h>
+
+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/roms/skiboot/libc/string/memcpy_from_ci.c b/roms/skiboot/libc/string/memcpy_from_ci.c
new file mode 100644
index 000000000..dd4d94e02
--- /dev/null
+++ b/roms/skiboot/libc/string/memcpy_from_ci.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2013-2016 IBM Corp
+ */
+
+#include <ccan/short_types/short_types.h>
+#include <io.h>
+#include <string.h>
+
+void *memcpy_from_ci(void *destpp, const void *srcpp, size_t len)
+{
+ const size_t block = sizeof(uint64_t);
+ unsigned long int destp = (long int) destpp;
+ unsigned long int srcp = (long int) srcpp;
+
+ /* Copy as many blocks as possible if srcp is block aligned */
+ if ((srcp % block) == 0) {
+ while ((len - block) > -1) {
+ uint64_t v;
+ if (HAVE_BIG_ENDIAN)
+ v = in_be64((beint64_t*)srcp);
+ else
+ v = in_le64((leint64_t*)srcp);
+ *((uint64_t *) destp) = v;
+ srcp += block;
+ destp += block;
+ len -= block;
+ }
+ }
+ /*
+ * Byte-by-byte copy if srcp is not block aligned or len is/becomes
+ * less than one block
+ */
+ while (len > 0) {
+ *((uint8_t*) destp) = in_8((uint8_t*)srcp);
+ srcp += 1;
+ destp += 1;
+ len--;
+ }
+ return destpp;
+}
diff --git a/roms/skiboot/libc/string/memmove.c b/roms/skiboot/libc/string/memmove.c
new file mode 100644
index 000000000..76aef6c87
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/memset.c b/roms/skiboot/libc/string/memset.c
new file mode 100644
index 000000000..f96a0231f
--- /dev/null
+++ b/roms/skiboot/libc/string/memset.c
@@ -0,0 +1,54 @@
+/******************************************************************************
+ * 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 <stddef.h>
+
+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 defined(__powerpc__) || defined(__powerpc64__)
+ if (size > CACHE_LINE_SIZE && c==0) {
+ while ((unsigned long long)d % CACHE_LINE_SIZE) {
+ *d++ = (unsigned char)c;
+ size--;
+ }
+ while (size >= CACHE_LINE_SIZE) {
+ asm volatile ("dcbz 0,%0\n" : : "r"(d) : "memory");
+ d+= CACHE_LINE_SIZE;
+ size-= CACHE_LINE_SIZE;
+ }
+ }
+#endif
+
+ 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/roms/skiboot/libc/string/strcasecmp.c b/roms/skiboot/libc/string/strcasecmp.c
new file mode 100644
index 000000000..ba1aedb5f
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <ctype.h>
+
+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/roms/skiboot/libc/string/strcat.c b/roms/skiboot/libc/string/strcat.c
new file mode 100644
index 000000000..329cc88e1
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/strchr.c b/roms/skiboot/libc/string/strchr.c
new file mode 100644
index 000000000..88f25f96b
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/strcmp.c b/roms/skiboot/libc/string/strcmp.c
new file mode 100644
index 000000000..5afbae2a7
--- /dev/null
+++ b/roms/skiboot/libc/string/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/roms/skiboot/libc/string/strcpy.c b/roms/skiboot/libc/string/strcpy.c
new file mode 100644
index 000000000..514be1714
--- /dev/null
+++ b/roms/skiboot/libc/string/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/roms/skiboot/libc/string/strdup.c b/roms/skiboot/libc/string/strdup.c
new file mode 100644
index 000000000..b0a4b4d70
--- /dev/null
+++ b/roms/skiboot/libc/string/strdup.c
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * Copyright (c) 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
+ *****************************************************************************/
+
+#include <stdlib.h>
+
+size_t strlen(const char *s);
+void *memcpy(void *dest, const void *src, size_t n);
+char *strdup(const char *src);
+char *strdup(const char *src)
+{
+ size_t len = strlen(src) + 1;
+ char *ret;
+
+ ret = malloc(len);
+ if (ret)
+ memcpy(ret, src, len);
+ return ret;
+}
diff --git a/roms/skiboot/libc/string/strlen.c b/roms/skiboot/libc/string/strlen.c
new file mode 100644
index 000000000..f3c5a8362
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/strncasecmp.c b/roms/skiboot/libc/string/strncasecmp.c
new file mode 100644
index 000000000..c6b158e60
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <ctype.h>
+
+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/roms/skiboot/libc/string/strncmp.c b/roms/skiboot/libc/string/strncmp.c
new file mode 100644
index 000000000..a5422c0dc
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/strncpy.c b/roms/skiboot/libc/string/strncpy.c
new file mode 100644
index 000000000..621c89b64
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/strrchr.c b/roms/skiboot/libc/string/strrchr.c
new file mode 100644
index 000000000..262a68287
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/strstr.c b/roms/skiboot/libc/string/strstr.c
new file mode 100644
index 000000000..cd9ccae9a
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/string/strtok.c b/roms/skiboot/libc/string/strtok.c
new file mode 100644
index 000000000..fcc3fce32
--- /dev/null
+++ b/roms/skiboot/libc/string/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 <stddef.h>
+
+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/roms/skiboot/libc/test/.gitignore b/roms/skiboot/libc/test/.gitignore
new file mode 100644
index 000000000..c1002af5b
--- /dev/null
+++ b/roms/skiboot/libc/test/.gitignore
@@ -0,0 +1,10 @@
+gmon.out
+run-ctype
+run-ctype-gcov
+run-memops
+run-memops-gcov
+run-snprintf
+run-snprintf-gcov
+run-stdlib
+run-stdlib-gcov
+
diff --git a/roms/skiboot/libc/test/Makefile.check b/roms/skiboot/libc/test/Makefile.check
new file mode 100644
index 000000000..a668334a1
--- /dev/null
+++ b/roms/skiboot/libc/test/Makefile.check
@@ -0,0 +1,74 @@
+# -*-Makefile-*-
+LIBC_TEST := libc/test/run-time
+
+# We have some tricky tests that have system libc and skiboot libc,
+# so that we can test parts of skiboot libc but in userspace.
+
+LIBC_DUALLIB_TEST := libc/test/run-snprintf \
+ libc/test/run-memops \
+ libc/test/run-stdlib \
+ libc/test/run-ctype
+
+LCOV_EXCLUDE += $(LIBC_TEST:%=%.c) $(LIBC_DUALLIB_TEST:%=%.c) $(LIBC_DUALLIB_TEST:%=%-test.c)
+
+.PHONY : libc-check libc-coverage
+libc-check: $(LIBC_TEST:%=%-check) $(LIBC_DUALLIB_TEST:%=%-check)
+libc-coverage: $(LIBC_TEST:%=%-gcov-run) $(LIBC_DUALLIB_TEST:%=%-gcov-run)
+
+check: libc-check
+coverage: libc-coverage
+
+$(LIBC_TEST:%=%-gcov-run) : %-run: %
+ $(call Q, TEST-COVERAGE ,$< , $<)
+
+$(LIBC_DUALLIB_TEST:%=%-gcov-run) : %-run: %
+ $(eval LCOV_DIRS += -d $(dir $<) )
+ $(call Q, TEST-COVERAGE , (cd $(dir $<); GCOV_PREFIX_STRIP=`(c=0; while [ "\`pwd\`" != '/' ]; do cd ..; c=\`expr 1 + $$c\`; done; echo $$c)` ./$(notdir $<) ), $< )
+
+$(LIBC_TEST:%=%-check) : %-check: %
+ $(call Q, RUN-TEST ,$(VALGRIND) $<, $<)
+
+$(LIBC_DUALLIB_TEST:%=%-check) : %-check: %
+ $(call Q, RUN-TEST ,$(VALGRIND) $<, $<)
+
+$(LIBC_TEST) : % : %.c
+ $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -I libfdt -I libc/include -o $@ $<, $<)
+
+$(LIBC_TEST:%=%-gcov): %-gcov : %.c %
+ $(call Q, HOSTCC ,(cd $(dir $<); $(HOSTCC) $(HOSTCFLAGS) $(HOSTGCOVCFLAGS) -I$(shell pwd)/include -I$(shell pwd) -I$(shell pwd)/libfdt -I$(shell pwd)/libc/include -o $(notdir $@) $(notdir $<)), $<)
+
+$(LIBC_DUALLIB_TEST) : % : %.o %-test.o
+ $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -I libfdt -o $@ $@-test.o $<, $<)
+
+$(LIBC_DUALLIB_TEST:%=%-gcov) : %-gcov : %-gcov.o %-gcov-test.o
+ $(call Q, HOSTCC ,(cd $(dir $<); $(HOSTCC) $(HOSTCFLAGS) $(HOSTGCOVCFLAGS) -I$(shell pwd)/include -I$(shell pwd)/. -I$(shell pwd)/libfdt -o $(notdir $@) $(notdir $@)-test.o $(notdir $<)), $<)
+
+$(LIBC_DUALLIB_TEST:%=%-test.o): %-test.o : %-test.c
+ $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -I libfdt -I libc/include -ffreestanding -o $@ -c $<, $<)
+
+$(LIBC_DUALLIB_TEST:%=%.o): %.o : %.c
+ $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -o $@ -c $<, $<)
+
+$(LIBC_DUALLIB_TEST:%=%-gcov.o): %-gcov.o : %.c
+ $(call Q, HOSTCC ,(cd $(dir $<); $(HOSTCC) $(HOSTCFLAGS) -fprofile-arcs -ftest-coverage -lgcov -pg -O0 -g -o $(notdir $@) -c $(notdir $<)), $<)
+
+$(LIBC_DUALLIB_TEST:%=%-gcov-test.o): %-gcov-test.o : %-test.c %
+ $(call Q, HOSTCC ,(cd $(dir $<); $(HOSTCC) $(HOSTCFLAGS) -fprofile-arcs -ftest-coverage -lgcov -pg -O0 -g -I$(shell pwd)/include -I$(shell pwd)/. -I$(shell pwd)/libfdt -I$(shell pwd)/libc/include -ffreestanding -o $(notdir $@) -c $(notdir $<) ), $<)
+
+-include $(wildcard libc/test/*.d)
+
+clean: libc-test-clean
+
+libc-test-clean:
+ $(RM) -f libc/test/*.[od]
+ $(RM) -f $(LIBC_TEST) \
+ $(LIBC_TEST:%=%-gcov) \
+ $(LIBC_TEST:%=%.gcda) \
+ $(LIBC_TEST:%=%.gcno)
+ $(RM) -f $(LIBC_DUALLIB_TEST) \
+ $(LIBC_DUALLIB_TEST:%=%-gcov) \
+ $(LIBC_DUALLIB_TEST:%=%-gcov.gcda) \
+ $(LIBC_DUALLIB_TEST:%=%-gcov.gcno) \
+ $(LIBC_DUALLIB_TEST:%=%-gcov-test.gcda) \
+ $(LIBC_DUALLIB_TEST:%=%-gcov-test.gcno) \
+ $(LIBC_DUALLIB_TEST:%=%-test.o)
diff --git a/roms/skiboot/libc/test/run-ctype-test.c b/roms/skiboot/libc/test/run-ctype-test.c
new file mode 100644
index 000000000..d491b4942
--- /dev/null
+++ b/roms/skiboot/libc/test/run-ctype-test.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2013-2015 IBM Corp.
+ *
+ * This file is run with the skiboot libc files rather than system libc.
+ * This means we have a bit of "fun" with actually executing the tests on
+ * the host.
+ * Patches to make this less ugly are very welcome.
+ */
+
+#include <config.h>
+#include <stdarg.h>
+
+#include "../ctype/isdigit.c"
+#include "../ctype/isprint.c"
+#include "../ctype/isspace.c"
+#include "../ctype/isxdigit.c"
+#include "../ctype/tolower.c"
+#include "../ctype/toupper.c"
+
+int skiboot_isdigit(int ch);
+int skiboot_isprint(int ch);
+int skiboot_isspace(int ch);
+int skiboot_isxdigit(int ch);
+int skiboot_tolower(int ch);
+int skiboot_toupper(int ch);
+
+int skiboot_isdigit(int ch)
+{
+ return isdigit(ch);
+}
+
+int skiboot_isprint(int ch)
+{
+ return isprint(ch);
+}
+
+int skiboot_isspace(int ch)
+{
+ return isspace(ch);
+}
+
+int skiboot_isxdigit(int ch)
+{
+ return isxdigit(ch);
+}
+
+int skiboot_tolower(int ch)
+{
+ return tolower(ch);
+}
+
+int skiboot_toupper(int ch)
+{
+ return toupper(ch);
+}
diff --git a/roms/skiboot/libc/test/run-ctype.c b/roms/skiboot/libc/test/run-ctype.c
new file mode 100644
index 000000000..a43d37123
--- /dev/null
+++ b/roms/skiboot/libc/test/run-ctype.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2013-2015 IBM Corp.
+ */
+
+#define BUFSZ 50
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+
+int skiboot_isdigit(int ch);
+int skiboot_isprint(int ch);
+int skiboot_isspace(int ch);
+int skiboot_isxdigit(int ch);
+int skiboot_tolower(int ch);
+int skiboot_toupper(int ch);
+
+int main(void)
+{
+ int i;
+ int r1, r2;
+
+ for(i = '0'; i <= '9'; i++)
+ assert(skiboot_isdigit(i));
+ assert(skiboot_isdigit('a') == 0);
+ assert(skiboot_isdigit('Z') == 0);
+
+ for (i = 0; i < 257; i++) {
+ r1 = skiboot_isdigit(i);
+ r2 = isdigit(i);
+ if (r1)
+ assert(r2);
+ if (!r1)
+ assert(!r2);
+ }
+
+ for(i = '0'; i <= '9'; i++)
+ assert(skiboot_isprint(i));
+ assert(skiboot_isprint('\0') == 0);
+ assert(skiboot_isprint(4) == 0);
+
+ for (i = 0; i < 257; i++) {
+ r1 = skiboot_isprint(i);
+ r2 = isprint(i);
+ if (r1)
+ assert(r2);
+ if (!r1)
+ assert(!r2);
+ }
+
+ for(i = '0'; i <= '9'; i++)
+ assert(skiboot_isspace(i) == 0);
+ assert(skiboot_isspace('\f'));
+ assert(skiboot_isspace('\n'));
+ assert(skiboot_isspace(' '));
+
+ for (i = 0; i < 257; i++) {
+ r1 = skiboot_isspace(i);
+ r2 = isspace(i);
+ if (r1)
+ assert(r2);
+ if (!r1)
+ assert(!r2);
+ }
+
+ for(i = '0'; i <= '9'; i++)
+ assert(skiboot_isxdigit(i));
+ assert(skiboot_isxdigit('a'));
+ assert(skiboot_isxdigit('A'));
+ assert(skiboot_isxdigit('F'));
+ assert(skiboot_isxdigit('Z') == 0);
+
+ for (i = 0; i < 257; i++) {
+ r1 = skiboot_isxdigit(i);
+ r2 = isxdigit(i);
+ if (r1)
+ assert(r2);
+ if (!r1)
+ assert(!r2);
+ }
+
+ for (i = 0; i < 257; i++) {
+ assert(skiboot_tolower(i) == tolower(i));
+ }
+
+ for (i = 0; i < 257; i++) {
+ assert(skiboot_toupper(i) == toupper(i));
+ }
+
+ return 0;
+}
diff --git a/roms/skiboot/libc/test/run-memops-test.c b/roms/skiboot/libc/test/run-memops-test.c
new file mode 100644
index 000000000..5be0d9ac1
--- /dev/null
+++ b/roms/skiboot/libc/test/run-memops-test.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2013-2015 IBM Corp.
+ *
+ * This file is run with the skiboot libc files rather than system libc.
+ * This means we have a bit of "fun" with actually executing the tests on
+ * the host.
+ * Patches to make this less ugly are very welcome.
+ */
+
+#include <config.h>
+#include <stdarg.h>
+
+#include "../string/memchr.c"
+#include "../string/memcmp.c"
+#include "../string/memcpy.c"
+#include "../string/memmove.c"
+#include "../string/memset.c"
+#include "../string/strcasecmp.c"
+#include "../string/strcat.c"
+#include "../string/strchr.c"
+#include "../string/strrchr.c"
+#include "../string/strcmp.c"
+#include "../string/strcpy.c"
+/* #include "../string/strdup.c" */
+#include "../string/strlen.c"
+#include "../string/strncasecmp.c"
+#include "../string/strncmp.c"
+#include "../string/strncpy.c"
+#include "../string/strstr.c"
+#include "../string/strtok.c"
+#include <stdlib.h>
+
+int test_memset(char* buf, int c, size_t s);
+int test_memchr(const void *ptr, int c, size_t n, void* expected);
+int test_memcmp(const void *ptr1, const void *ptr2, size_t n, int expected);
+int test_strcmp(const void *ptr1, const void *ptr2, int expected);
+int test_strchr(const char *s, int c, char *expected);
+int test_strrchr(const char *s, int c, char *expected);
+int test_strcasecmp(const char *s1, const char *s2, int expected);
+int test_strncasecmp(const char *s1, const char *s2, size_t n, int expected);
+int test_memmove(void *dest, const void *src, size_t n, const void *r, const void *expected, size_t expected_n);
+
+int test_memset(char* buf, int c, size_t s)
+{
+ int i;
+ int r= 0;
+
+ memset(buf, c, s);
+ for(i=0; i<s; i++)
+ if (buf[i] != c)
+ r = -1;
+
+ return r;
+}
+
+int test_memchr(const void *ptr, int c, size_t n, void* expected)
+{
+ return(expected == memchr(ptr, c, n));
+}
+
+int test_memcmp(const void *ptr1, const void *ptr2, size_t n, int expected)
+{
+ return(expected == memcmp(ptr1, ptr2, n));
+}
+
+int test_strcmp(const void *ptr1, const void *ptr2, int expected)
+{
+ return(expected == strcmp(ptr1, ptr2));
+}
+
+int test_strchr(const char *s, int c, char *expected)
+{
+ return(expected == strchr(s, c));
+}
+
+int test_strrchr(const char *s, int c, char *expected)
+{
+ return(expected == strrchr(s, c));
+}
+
+int test_strcasecmp(const char *s1, const char *s2, int expected)
+{
+ return(expected == strcasecmp(s1, s2));
+}
+
+int test_strncasecmp(const char *s1, const char *s2, size_t n, int expected)
+{
+ return(expected == strncasecmp(s1, s2, n));
+}
+
+int test_memmove(void *dest, const void *src, size_t n, const void *r, const void *expected, size_t expected_n)
+{
+ if (memmove(dest, src, n) != dest)
+ return -1;
+ return(memcmp(r, expected, expected_n) == 0);
+}
diff --git a/roms/skiboot/libc/test/run-memops.c b/roms/skiboot/libc/test/run-memops.c
new file mode 100644
index 000000000..a00c2fb36
--- /dev/null
+++ b/roms/skiboot/libc/test/run-memops.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2013-2015 IBM Corp.
+ */
+
+#define BUFSZ 50
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+int test_memset(char* buf, int c, size_t s);
+int test_memchr(const void *ptr, int c, size_t n, void* expected);
+int test_memcmp(const void *ptr1, const void *ptr2, size_t n, int expected);
+int test_strcmp(const void *ptr1, const void *ptr2, int expected);
+int test_strchr(const char *s, int c, char *expected);
+int test_strrchr(const char *s, int c, char *expected);
+int test_strcasecmp(const char *s1, const char *s2, int expected);
+int test_strncasecmp(const char *s1, const char *s2, size_t n, int expected);
+int test_memmove(void *dest, const void *src, size_t n, const void *r, const void *expected, size_t expected_n);
+
+int main(void)
+{
+ char *buf;
+ char *buf2;
+
+ buf = malloc(100);
+ assert(test_memset(buf, 0x42, 100) == 0);
+ free(buf);
+
+ buf = malloc(128);
+ assert(test_memset(buf, 0, 128) == 0);
+ assert(test_memset(buf+1, 0, 127) == 0);
+ free(buf);
+
+ buf = malloc(1024);
+ assert(test_memset(buf, 0, 1024) == 0);
+ free(buf);
+
+ buf = malloc(20);
+ strncpy(buf, "Hello World!", 20);
+ assert(test_memchr(buf, 'o', strlen(buf), buf+4));
+ assert(test_memchr(buf, 'a', strlen(buf), NULL));
+
+ assert(test_memcmp(buf, "Hello World!", strlen(buf), 0));
+ assert(test_memcmp(buf, "Hfllow World", strlen(buf), -1));
+
+ assert(test_strcmp(buf, "Hello World!", 0));
+ assert(test_strcmp(buf, "Hfllow World", -1));
+
+ assert(test_strchr(buf, 'H', buf));
+ assert(test_strchr(buf, 'e', buf+1));
+ assert(test_strchr(buf, 'a', NULL));
+ assert(test_strchr(buf, '!', buf+11));
+
+ assert(test_strrchr(buf, 'H', buf));
+ assert(test_strrchr(buf, 'o', buf+7));
+ assert(test_strrchr(buf, 'a', NULL));
+ assert(test_strrchr(buf, 'l', buf+9));
+ assert(test_strrchr(buf, '!', buf+11));
+
+ assert(test_strcasecmp(buf, "Hello World!", 0));
+ assert(test_strcasecmp(buf, "HELLO WORLD!", 0));
+ assert(test_strcasecmp(buf, "IELLO world!", -1));
+ assert(test_strcasecmp(buf, "HeLLo WOrlc!", 1));
+
+ assert(test_strncasecmp(buf, "Hello World!", strlen(buf), 0));
+ assert(test_strncasecmp(buf, "HELLO WORLD!", strlen(buf), 0));
+ assert(test_strncasecmp(buf, "IELLO world!", strlen(buf), -1));
+ assert(test_strncasecmp(buf, "HeLLo WOrlc!", strlen(buf), 1));
+
+ assert(test_strncasecmp(buf, "HeLLo WOrlc!", 0, 0));
+ assert(test_strncasecmp(buf, "HeLLo WOrlc!", 1, 0));
+ assert(test_strncasecmp(buf, "HeLLo WOrlc!", 2, 0));
+ assert(test_strncasecmp(buf, "HeLLp WOrlc!", 5, -1));
+
+ free(buf);
+
+ buf = malloc(20);
+ buf2 = malloc(20);
+ strncpy(buf, "Hello", 20);
+ strncpy(buf2, " World!", 20);
+
+ assert(test_memmove(buf + 5, buf2, strlen(buf2), buf,
+ "Hello World!", strlen("Hello World!")));
+
+ strncpy(buf, "HHello World!", 20);
+ assert(test_memmove(buf, buf+1, strlen("Hello World!"), buf, "Hello World!", strlen("Hello World!")));
+
+ strncpy(buf, "0123456789", 20);
+ assert(test_memmove(buf+1, buf , strlen("0123456789"), buf, "00123456789", strlen("00123456789")));
+
+ free(buf);
+ free(buf2);
+
+ return 0;
+}
diff --git a/roms/skiboot/libc/test/run-snprintf-test.c b/roms/skiboot/libc/test/run-snprintf-test.c
new file mode 100644
index 000000000..a6ad02373
--- /dev/null
+++ b/roms/skiboot/libc/test/run-snprintf-test.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2013-2015 IBM Corp.
+ *
+ * This file is run with the skiboot libc files rather than system libc.
+ * This means we have a bit of "fun" with actually executing the tests on
+ * the host.
+ * Patches to make this less ugly are very welcome.
+ */
+
+#include <config.h>
+#include <stdarg.h>
+
+#include "../stdio/snprintf.c"
+#include "../stdio/vsnprintf.c"
+
+int test1(void);
+
+int test1(void)
+{
+ return snprintf(NULL, 1, "Hello");
+}
+
+int skiboot_snprintf(char *buf, size_t bufsz, size_t l, const char* format, ...);
+
+int skiboot_snprintf(char *buf, size_t bufsz, size_t l, const char* format, ...)
+{
+ va_list ar;
+ int count;
+
+ if (buf)
+ memset(buf, 0, bufsz);
+
+ if ((buf==NULL) || (format==NULL))
+ return(-1);
+
+ va_start(ar, format);
+ count = vsnprintf(buf, l, format, ar);
+ va_end(ar);
+
+ return(count);
+}
diff --git a/roms/skiboot/libc/test/run-snprintf.c b/roms/skiboot/libc/test/run-snprintf.c
new file mode 100644
index 000000000..946d446fa
--- /dev/null
+++ b/roms/skiboot/libc/test/run-snprintf.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2013-2015 IBM Corp.
+ */
+
+#define BUFSZ 50
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+int test1(void);
+int skiboot_snprintf(char *buf, size_t bufsz, size_t l, const char* format, ...);
+
+static void test_printf_0u(int n)
+{
+ char *buf, *buf2;
+ int blen;
+ unsigned int i;
+
+ for(i=1; i<10; i++)
+ {
+ blen = i+1;
+ if (n<0)
+ blen++;
+
+ buf = (char*)malloc(blen);
+ buf2 = (char*)malloc(blen);
+ skiboot_snprintf(buf, blen, blen, "%08u", n);
+ snprintf(buf2, blen, "%08u", n);
+ n = n * 10;
+ assert(0 == strncmp(buf, buf2, blen));
+ free(buf);
+ free(buf2);
+ }
+}
+
+static void test_printf_u(int n)
+{
+ char *buf, *buf2;
+ int blen;
+ unsigned int r;
+ unsigned int i;
+
+ for(i=1; i<10; i++)
+ {
+ blen = i+1;
+ if (n<0)
+ blen++;
+
+ buf = (char*)malloc(blen);
+ buf2 = (char*)malloc(blen);
+ r = skiboot_snprintf(buf, blen, blen, "%u", n);
+ snprintf(buf2, blen, "%u", n);
+ n = n * 10;
+ if (n<0)
+ assert(i+1 == r);
+ else
+ assert(i == r);
+ assert(0 == strncmp(buf, buf2, blen));
+ free(buf);
+ free(buf2);
+ }
+}
+
+static void test_printf_d(int n)
+{
+ char *buf, *buf2;
+ int blen;
+ int r;
+ int i;
+
+ for(i=1; i<10; i++)
+ {
+ blen = i+1;
+ if (n<0)
+ blen++;
+
+ buf = (char*)malloc(blen);
+ buf2 = (char*)malloc(blen);
+ r = skiboot_snprintf(buf, blen, blen, "%d", n);
+ snprintf(buf2, blen, "%d", n);
+ n = n * 10;
+ if (n<0)
+ assert(i+1 == r);
+ else
+ assert(i == r);
+ assert(0 == strncmp(buf, buf2, blen));
+ free(buf);
+ free(buf2);
+ }
+}
+
+static void test_printf_x(const char* f)
+{
+ char *buf, *buf2;
+ int blen;
+ int i, r;
+ unsigned int n=0x1;
+
+ for (i=0; i<8; i++)
+ {
+ blen = i+2;
+ buf = (char*)malloc(blen);
+ buf2 = (char*)malloc(blen);
+ r = skiboot_snprintf(buf, blen, blen, f, n);
+ snprintf(buf2, blen, f, n);
+ assert(i+1 == r);
+ assert(0 == strncmp(buf, buf2, blen));
+ free(buf);
+ free(buf2);
+ n = n << 4;
+ }
+}
+
+static void test_printf_c(void)
+{
+ char *buf= (char*)malloc(2);
+ char buf2[2];
+ unsigned char i= 0xff;
+ int r;
+ while(i)
+ {
+ r = skiboot_snprintf(buf, 2, 2, "%c", i);
+ snprintf(buf2, 2, "%c", i);
+ assert(r==1);
+ assert(0 == strncmp(buf, buf2, 2));
+ i--;
+ }
+ free(buf);
+}
+
+static void test_printf_p(void)
+{
+ char *buf= (char*)malloc(32);
+ char buf2[32];
+ skiboot_snprintf(buf, 32, 32, "%p", buf);
+ snprintf(buf2, 32, "%p", buf);
+ assert(0 == strncmp(buf, buf2, 32));
+ free(buf);
+}
+
+static void test_printf_o(void)
+{
+ char *buf= (char*)malloc(32);
+ char buf2[32];
+ skiboot_snprintf(buf, 32, 32, "%o", 0x12345678);
+ snprintf(buf2, 32, "%o", 0x12345678);
+ assert(0 == strncmp(buf, buf2, 32));
+ free(buf);
+}
+
+static void test_printf_h(short i)
+{
+ char *buf= (char*)malloc(32);
+ char buf2[32];
+ skiboot_snprintf(buf, 32, 32, "%hd", i);
+ snprintf(buf2, 32, "%hd", i);
+ assert(0 == strncmp(buf, buf2, 32));
+ free(buf);
+}
+
+static void test_printf_z(size_t i)
+{
+ char *buf= (char*)malloc(32);
+ char buf2[32];
+ skiboot_snprintf(buf, 32, 32, "%zu", i);
+ snprintf(buf2, 32, "%zu", i);
+ assert(0 == strncmp(buf, buf2, 32));
+ free(buf);
+}
+
+int main(void)
+{
+ char *buf;
+ int r;
+
+ buf = (char*)malloc(BUFSZ);
+ memset(buf, 0, BUFSZ);
+
+ assert(-1 == test1());
+
+ r = skiboot_snprintf(buf, BUFSZ, 2, "%%");
+ assert(r==1);
+ assert(buf[0] == '%' && buf[1] == 0);
+
+ r = skiboot_snprintf(buf, BUFSZ, 2, "%d", 137);
+ /* BUG/FIXME:
+ * skiboot libc does NOT return the length of the buffer you'd need
+ * Instead, it'll return something random, possibly zero (as here)
+ * but as you'll see in test_in_buf_len2, sometimes not.
+ *
+ * Basically, we're not POSIX printf and this is some day going to
+ * cause things to be awful.
+ */
+ assert(0 == r); // BUG, should be 3
+ assert(0 == strncmp(buf, "", 3));
+
+ r = skiboot_snprintf(buf, BUFSZ, 4, "%d", 137);
+ assert(3 == r);
+ assert(0 == strncmp(buf, "137", 3));
+ assert(buf[3] == 0);
+
+ /* Now we test the strange behaviour of our printf.
+ * For strings, we get partial prints going, but if we whack an
+ * integer on the end, we may or may not get that integer, depending
+ * on if we have enough size. We should test that though */
+
+ r = skiboot_snprintf(buf, BUFSZ, 4, "Hello %d", 137);
+ assert(3 == r);
+ assert(0 == strncmp(buf, "Hel", 3));
+ assert(buf[3] == 0);
+ r = skiboot_snprintf(buf, BUFSZ, 7, "Hello %d", 137);
+ assert(6 == r);
+ assert(0 == strncmp(buf, "Hello ", 6));
+ assert(buf[6] == 0);
+ r = skiboot_snprintf(buf, BUFSZ, 10, "Hello %d", 137);
+ assert(9 == r);
+ assert(0 == strncmp(buf, "Hello 137", 10));
+ assert(buf[9] == 0);
+ free(buf);
+
+ test_printf_u(1);
+ test_printf_0u(1);
+ test_printf_d(1);
+ test_printf_d(-1);
+ test_printf_x("%x");
+ test_printf_x("%X");
+ test_printf_c();
+ test_printf_p();
+ test_printf_o();
+ test_printf_h(0);
+ test_printf_h(128);
+ test_printf_h(256);
+ test_printf_h(-1);
+ test_printf_h(32767);
+ test_printf_h(32768);
+ test_printf_h(65535);
+ test_printf_z(0);
+ test_printf_z(-1);
+ test_printf_z(12345);
+ test_printf_z(128000000);
+
+ return 0;
+}
diff --git a/roms/skiboot/libc/test/run-stdlib-test.c b/roms/skiboot/libc/test/run-stdlib-test.c
new file mode 100644
index 000000000..f7d7137c9
--- /dev/null
+++ b/roms/skiboot/libc/test/run-stdlib-test.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2013-2015 IBM Corp.
+ *
+ * This file is run with the skiboot libc files rather than system libc.
+ * This means we have a bit of "fun" with actually executing the tests on
+ * the host.
+ * Patches to make this less ugly are very welcome.
+ */
+
+#include <config.h>
+#include <stdarg.h>
+
+#include "../stdlib/atoi.c"
+#include "../stdlib/atol.c"
+#include "../stdlib/error.c"
+#include "../stdlib/rand.c"
+#include "../stdlib/strtol.c"
+#include "../stdlib/strtoul.c"
diff --git a/roms/skiboot/libc/test/run-stdlib.c b/roms/skiboot/libc/test/run-stdlib.c
new file mode 100644
index 000000000..174920897
--- /dev/null
+++ b/roms/skiboot/libc/test/run-stdlib.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2013-2015 IBM Corp.
+ */
+
+#define BUFSZ 50
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+int main(void)
+{
+ char buf[] = "42, and stuff.";
+ char *ptr;
+
+ /* atoi/strtol - general correct behavior */
+ assert(atoi("0") == 0);
+ assert(atoi("1") == 1);
+ assert(atoi(" 123456") == 123456);
+ assert(atoi("-72") == -72);
+ assert(atoi(" -84") == -84);
+ assert(atoi("2147483647") == 2147483647);
+
+ /* atoi/strtol - numbers before and after strings */
+ assert(atoi("hello!123") == 0);
+ assert(atoi(buf) == 42);
+ assert(atoi("42isthemagicnumber") == 42);
+
+ /* atoi is base 10 only */
+ assert(atoi("0x800") == 0);
+
+ /* atol - ensure it recognises longs */
+ assert(atol("2147483648") == 2147483648);
+ assert(atol("-2147483649") == -2147483649);
+
+ /* strtol detects hex */
+ assert(strtol("0x800", NULL, 0) == 0x800);
+ /* But not with a duplicate prefix */
+ assert(strtol("0x0x800", NULL, 0) == 0);
+
+ /* strtol - invalid/weird bases */
+ assert(strtol("z", NULL, -1) == 0);
+ assert(strtol("11111", NULL, 1) == 0);
+ assert(strtol("z", NULL, 37) == 0);
+ assert(strtol("z", NULL, 36) == 35);
+ assert(strtol("-Y", NULL, 36) == -34);
+
+ /* strtol - ptr advanced correctly */
+ ptr = buf;
+ assert(strtol(buf, &ptr, 10) == 42);
+ assert(ptr == buf + 2);
+
+ /* strtoul - base 10 */
+ assert(strtoul("0", NULL, 10) == 0);
+ assert(strtoul("1", NULL, 10) == 1);
+ assert(strtoul(" 123456", NULL, 10) == 123456);
+ assert(strtoul("-72", NULL, 10) == 0);
+ assert(strtoul("9999999999", NULL, 10) == 9999999999);
+ assert(strtoul("hello!123", NULL, 10) == 0);
+ assert(strtoul(buf, NULL, 10) == 42);
+ assert(strtoul("42isthemagicnumber", NULL, 10) == 42);
+
+ /* strtoul - autodetection of base */
+ assert(strtoul(" 123456", NULL, 0) == 123456);
+ assert(strtoul("0x800", NULL, 0) == 0x800);
+ assert(strtoul("0x0x800", NULL, 0) == 0);
+
+ /* strtoul - weird/invalid bases */
+ assert(strtoul("z", NULL, -1) == 0);
+ assert(strtoul("11111", NULL, 1) == 0);
+ assert(strtoul("z", NULL, 37) == 0);
+ assert(strtoul("z", NULL, 36) == 35);
+ assert(strtoul("Y", NULL, 36) == 34);
+
+ /* labs - ensure it returns absolute value */
+ assert(labs(0) == 0);
+ assert(labs(2147483647) == 2147483647);
+ assert(labs(-2147483647) == 2147483647);
+ assert(labs(9223372036854775807) == 9223372036854775807);
+ assert(labs(-9223372036854775807) == 9223372036854775807);
+
+ return 0;
+}
diff --git a/roms/skiboot/libc/test/run-time.c b/roms/skiboot/libc/test/run-time.c
new file mode 100644
index 000000000..95e83e5a9
--- /dev/null
+++ b/roms/skiboot/libc/test/run-time.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Copyright 2014-2015 IBM Corp.
+ */
+#include "/usr/include/assert.h"
+#include <stdio.h>
+#include <libc/include/time.h>
+#include <stdint.h>
+
+#include "../time.c"
+
+#define MKTIME_TEST(Y,M,D,h,m,s,t) \
+ tm.tm_year = Y; \
+ tm.tm_mon = M; \
+ tm.tm_mday = D; \
+ tm.tm_hour = h; \
+ tm.tm_min = m; \
+ tm.tm_sec = s; \
+ assert(mktime(&tm) == t); \
+ assert(tm.tm_year == Y); \
+ assert(tm.tm_mon == M); \
+ assert(tm.tm_mday == D); \
+ assert(tm.tm_hour == h); \
+ assert(tm.tm_min == m); \
+ assert(tm.tm_sec == s)
+
+#define GMTIME_TEST(Y,M,D,h,m,s,tv) \
+ t = tv; \
+ gmtime_r(&t, &tm); \
+ assert(tm.tm_year == Y); \
+ assert(tm.tm_mon == M); \
+ assert(tm.tm_mday == D); \
+ assert(tm.tm_hour == h); \
+ assert(tm.tm_min == m); \
+ assert(tm.tm_sec == s)
+
+#define TIME_TEST(Y,M,D,h,m,s,tv) \
+ MKTIME_TEST(Y,M,D,h,m,s,tv); \
+ GMTIME_TEST(Y,M,D,h,m,s,tv)
+
+int main(void)
+{
+ struct tm tm;
+ time_t t = 0;
+
+ TIME_TEST(1970, 0, 1, 0, 0, 0, 0);
+ TIME_TEST(1971, 0, 1, 0, 0, 0, 365*SECS_PER_DAY);
+ TIME_TEST(1972, 0, 1, 0, 0, 0, 2*365*SECS_PER_DAY);
+ TIME_TEST(1972, 11, 31, 0, 0, 0, 3*365*SECS_PER_DAY);
+ TIME_TEST(1973, 0, 1, 0, 0, 0, (3*365+1)*SECS_PER_DAY);
+ TIME_TEST(2000, 11, 31, 0, 0, 0, 978220800);
+ TIME_TEST(2001, 0, 1, 0, 0, 0, 978307200);
+ TIME_TEST(2003, 11, 31, 0, 0, 0, 1072828800);
+ TIME_TEST(2004, 0, 1, 0, 0, 0, 1072828800+SECS_PER_DAY);
+ TIME_TEST(2004, 11, 29, 0, 0, 0, 1072828800+364*SECS_PER_DAY);
+ TIME_TEST(2004, 11, 30, 0, 0, 0, 1072828800+365*SECS_PER_DAY);
+ TIME_TEST(2004, 11, 31, 0, 0, 0, 1072828800+366*SECS_PER_DAY);
+ TIME_TEST(2004, 11, 31, 23, 59, 59, 1072828800+367*SECS_PER_DAY-1);
+ TIME_TEST(2100, 11, 31, 0, 0, 0, 4133894400);
+ TIME_TEST(2101, 0, 1, 0, 0, 0, 4133980800);
+
+ /* Test the normalisation functionality of mktime */
+ tm.tm_year = 2000;
+ tm.tm_mon = 1;
+ tm.tm_mday = 10;
+ tm.tm_hour = 5;
+ tm.tm_min = 32;
+ tm.tm_sec = 105;
+ mktime(&tm);
+ assert(tm.tm_year == 2000);
+ assert(tm.tm_mon == 1);
+ assert(tm.tm_mday == 10);
+ assert(tm.tm_hour == 5);
+ assert(tm.tm_min == 33);
+ assert(tm.tm_sec == 45);
+ tm.tm_sec += 366*24*60*60;
+ mktime(&tm);
+ assert(tm.tm_year == 2001);
+ assert(tm.tm_mon == 1);
+ assert(tm.tm_mday == 10);
+ assert(tm.tm_hour == 5);
+ assert(tm.tm_min == 33);
+ assert(tm.tm_sec == 45);
+
+ return 0;
+}
diff --git a/roms/skiboot/libc/time.c b/roms/skiboot/libc/time.c
new file mode 100644
index 000000000..71bbdff64
--- /dev/null
+++ b/roms/skiboot/libc/time.c
@@ -0,0 +1,142 @@
+#include <stdbool.h>
+#include <time.h>
+
+/*
+ * Returns the number of leap years prior to the given year.
+ */
+static int leap_years(int year)
+{
+ return (year-1)/4 + (year-1)/400 - (year-1)/100;
+}
+
+static int is_leap_year(int year)
+{
+ return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
+}
+
+static int days_in_month(int month, int year)
+{
+ static char month_days[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
+ };
+
+ /* we may need to update this in the year 4000, pending a
+ * decision on whether or not it's a leap year */
+ if (month == 1)
+ return is_leap_year(year) ? 29 : 28;
+
+ return month_days[month];
+}
+
+static const int days_per_month[2][13] =
+ {{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
+ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
+
+#define SECS_PER_MIN 60
+#define SECS_PER_HOUR (SECS_PER_MIN*60)
+#define SECS_PER_DAY (24*SECS_PER_HOUR)
+#define DAYS_PER_YEAR 365
+struct tm *gmtime_r(const time_t *timep, struct tm *result)
+{
+ int i;
+ int Y;
+ int M;
+ int D;
+ int h;
+ int m;
+ int s;
+
+ D = *timep / SECS_PER_DAY;
+ s = *timep % SECS_PER_DAY;
+ m = s / 60;
+ h = m / 60;
+ m %= 60;
+ s %= 60;
+
+ /*
+ * Work out the year. We subtract one day for every four years
+ * and every 400 years after 1969. However as leap years don't
+ * occur every 100 years we add one day back to counteract the
+ * the subtraction for every 4 years.
+ */
+ Y = (D - (1+D/365)/4 + (69+D/365)/100 - (369+D/365)/400)/365;
+
+ /*
+ * Remember we're doing integer arithmetic here so
+ * leap_years(Y+1970) - leap_years(1970) != leap_years(Y)
+ */
+ D = D - Y*365 - (leap_years(Y+1970) - leap_years(1970)) + 1;
+ Y += 1970;
+
+ M = 0;
+ for (i = 0; i < 13; i++)
+ if (D <= days_per_month[is_leap_year(Y) ? 1 : 0][i]) {
+ M = i;
+ break;
+ }
+
+ D -= days_per_month[is_leap_year(Y)][M-1];
+ result->tm_year = Y;
+ result->tm_mon = M - 1;
+ result->tm_mday = D;
+ result->tm_hour = h;
+ result->tm_min = m;
+ result->tm_sec = s;
+ return result;
+}
+
+time_t mktime(struct tm *tm)
+{
+ unsigned long year, month, mday, hour, minute, second, d;
+ static const unsigned long sec_in_400_years =
+ ((3903ul * 365) + (97 * 366)) * 24 * 60 * 60;
+
+ second = tm->tm_sec;
+ minute = tm->tm_min;
+ hour = tm->tm_hour;
+ mday = tm->tm_mday;
+ month = tm->tm_mon;
+ year = tm->tm_year;
+
+ /* There are the same number of seconds in any 400-year block; this
+ * limits the iterations in the loop below */
+ year += 400 * (second / sec_in_400_years);
+ second = second % sec_in_400_years;
+
+ if (second >= 60) {
+ minute += second / 60;
+ second = second % 60;
+ }
+
+ if (minute >= 60) {
+ hour += minute / 60;
+ minute = minute % 60;
+ }
+
+ if (hour >= 24) {
+ mday += hour / 24;
+ hour = hour % 24;
+ }
+
+ for (d = days_in_month(month, year); mday > d;
+ d = days_in_month(month, year)) {
+ month++;
+ if (month > 11) {
+ month = 0;
+ year++;
+ }
+ mday -= d;
+ }
+
+ tm->tm_year = year;
+ tm->tm_mon = month;
+ tm->tm_mday = mday;
+ tm->tm_hour = hour;
+ tm->tm_min = minute;
+ tm->tm_sec = second;
+
+ d = mday;
+ d += days_per_month[is_leap_year(year)][month];
+ d += (year-1970)*DAYS_PER_YEAR + leap_years(year) - leap_years(1970) - 1;
+ return d*SECS_PER_DAY + hour*SECS_PER_HOUR + minute*SECS_PER_MIN + second;
+}