From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001
From: Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com>
Date: Tue, 10 Oct 2023 14:33:42 +0000
Subject: Add submodule dependency files

Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
---
 roms/openbios/libc/build.xml  |  12 ++
 roms/openbios/libc/ctype.c    |  34 ++++
 roms/openbios/libc/diskio.c   | 248 +++++++++++++++++++++++
 roms/openbios/libc/extra.c    |  49 +++++
 roms/openbios/libc/misc.c     | 144 ++++++++++++++
 roms/openbios/libc/string.c   | 384 ++++++++++++++++++++++++++++++++++++
 roms/openbios/libc/vsprintf.c | 448 ++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 1319 insertions(+)
 create mode 100644 roms/openbios/libc/build.xml
 create mode 100644 roms/openbios/libc/ctype.c
 create mode 100644 roms/openbios/libc/diskio.c
 create mode 100644 roms/openbios/libc/extra.c
 create mode 100644 roms/openbios/libc/misc.c
 create mode 100644 roms/openbios/libc/string.c
 create mode 100644 roms/openbios/libc/vsprintf.c

(limited to 'roms/openbios/libc')

diff --git a/roms/openbios/libc/build.xml b/roms/openbios/libc/build.xml
new file mode 100644
index 000000000..cb2b560db
--- /dev/null
+++ b/roms/openbios/libc/build.xml
@@ -0,0 +1,12 @@
+<build>
+
+ <library name="libc" type="static" target="target">
+  <object source="ctype.c"/>
+  <object source="diskio.c"/>
+  <object source="extra.c"/>
+  <object source="misc.c"/>
+  <object source="string.c"/>
+  <object source="vsprintf.c"/>
+ </library>
+  
+</build>
diff --git a/roms/openbios/libc/ctype.c b/roms/openbios/libc/ctype.c
new file mode 100644
index 000000000..c433f6c62
--- /dev/null
+++ b/roms/openbios/libc/ctype.c
@@ -0,0 +1,34 @@
+/*
+ *  linux/lib/ctype.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include "config.h"
+#include "libc/string.h"
+
+const unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C,			/* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,		/* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C,			/* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C,			/* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,			/* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P,			/* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D,			/* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P,			/* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,	/* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U,			/* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U,			/* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P,			/* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,	/* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L,			/* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L,			/* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C,			/* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
diff --git a/roms/openbios/libc/diskio.c b/roms/openbios/libc/diskio.c
new file mode 100644
index 000000000..23f38ebb2
--- /dev/null
+++ b/roms/openbios/libc/diskio.c
@@ -0,0 +1,248 @@
+/*
+ *   Creation Date: <2003/12/07 19:36:00 samuel>
+ *   Time-stamp: <2004/01/07 19:28:43 samuel>
+ *
+ *	<diskio.c>
+ *
+ *	I/O wrappers
+ *
+ *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+
+//#define CONFIG_DEBUG_DISKIO
+#ifdef CONFIG_DEBUG_DISKIO
+#define DPRINTF(fmt, args...)                   \
+    do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+typedef struct {
+	ihandle_t ih;
+	int	do_close;
+	xt_t	read_xt;
+	xt_t	seek_xt;
+
+	xt_t	reopen_xt;
+	xt_t	tell_xt;
+	xt_t	get_path_xt;
+	xt_t	get_fstype_xt;
+	xt_t	open_nwrom_xt;
+	xt_t	volume_name_xt;
+} priv_fd_t;
+
+#define MAX_FD 32
+static priv_fd_t *file_descriptors[MAX_FD];
+
+static int
+lookup_xt( ihandle_t ih, const char *method, xt_t *xt )
+{
+	if( *xt )
+		return 0;
+	*xt = find_ih_method( method, ih );
+	return (*xt) ? 0:1;
+}
+
+int
+open_ih( ihandle_t ih )
+{
+	xt_t read_xt=0, seek_xt=0;
+	priv_fd_t *fdp;
+	int fd;
+
+	if( !ih || lookup_xt(ih, "read", &read_xt) )
+		return -1;
+	if( lookup_xt(ih, "seek", &seek_xt) )
+		return -1;
+
+	for (fd=0; fd<MAX_FD; fd++)
+		if(file_descriptors[fd]==NULL)
+			break;
+	if(fd==MAX_FD)
+		return -1;
+
+	fdp = malloc( sizeof(*fdp) );
+	/* Better clear the fd, as it
+	 * contains valuable information
+	 */
+	memset(fdp, 0, sizeof(*fdp));
+	fdp->ih = ih;
+	fdp->read_xt = read_xt;
+	fdp->seek_xt = seek_xt;
+	fdp->do_close = 0;
+
+	file_descriptors[fd]=fdp;
+        DPRINTF("%s(0x%lx) = %d\n", __func__, (unsigned long)ih, fd);
+	return fd;
+}
+
+int
+open_io( const char *spec )
+{
+	int fd;
+	ihandle_t ih = open_dev( spec );
+	priv_fd_t *fdp;
+
+        DPRINTF("%s(%s)\n", __func__, spec);
+	if( !ih )
+		return -1;
+
+	if( (fd=open_ih(ih)) == -1 ) {
+		close_dev( ih );
+		return -1;
+	}
+
+	fdp = file_descriptors[fd];
+	fdp->do_close = 1;
+
+	return fd;
+}
+
+int
+reopen( int fd, const char *filename )
+{
+	priv_fd_t *fdp = file_descriptors[fd];
+	int ret;
+
+	if( lookup_xt(fdp->ih, "reopen", &fdp->reopen_xt) )
+		return -1;
+
+	push_str( filename );
+	call_package( fdp->reopen_xt, fdp->ih );
+        ret = (POP() == (ucell)-1)? 0 : -1;
+
+        DPRINTF("%s(%d, %s) = %d\n", __func__, fd, filename, ret);
+	return ret;
+}
+
+int
+reopen_nwrom( int fd )
+{
+	priv_fd_t *fdp = file_descriptors[fd];
+
+        DPRINTF("%s(%d)\n", __func__, fd);
+	if( lookup_xt(fdp->ih, "open-nwrom", &fdp->open_nwrom_xt) )
+		return -1;
+	call_package( fdp->open_nwrom_xt, fdp->ih );
+        return (POP() == (ucell)-1)? 0 : -1;
+}
+
+ihandle_t
+get_ih_from_fd( int fd )
+{
+	priv_fd_t *fdp = file_descriptors[fd];
+	return fdp->ih;
+}
+
+const char *
+get_file_path( int fd )
+{
+	priv_fd_t *fdp = file_descriptors[fd];
+	if( lookup_xt(fdp->ih, "get-path", &fdp->get_path_xt) )
+		return NULL;
+	call_package( fdp->get_path_xt, fdp->ih );
+	return (char*)cell2pointer(POP());
+}
+
+const char *
+get_volume_name( int fd )
+{
+	priv_fd_t *fdp = file_descriptors[fd];
+	if( lookup_xt(fdp->ih, "volume-name", &fdp->volume_name_xt) )
+		return NULL;
+	call_package( fdp->volume_name_xt, fdp->ih );
+	return (char*)cell2pointer(POP());
+}
+
+const char *
+get_fstype( int fd )
+{
+	priv_fd_t *fdp = file_descriptors[fd];
+	if( lookup_xt(fdp->ih, "get-fstype", &fdp->get_fstype_xt) )
+		return NULL;
+	call_package( fdp->get_fstype_xt, fdp->ih );
+	return (char*)cell2pointer(POP());
+}
+
+int
+read_io( int fd, void *buf, size_t cnt )
+{
+	priv_fd_t *fdp;
+	ucell ret;
+
+        DPRINTF("%s(%d, %p, %u)\n", __func__, fd, buf, cnt);
+	if (fd != -1) {
+		fdp = file_descriptors[fd];
+
+		PUSH( pointer2cell(buf) );
+		PUSH( cnt );
+		call_package( fdp->read_xt, fdp->ih );
+		ret = POP();
+
+		if( !ret && cnt )
+			ret = -1;
+	} else {
+		ret = -1;
+	}
+
+	return ret;
+}
+
+int
+seek_io( int fd, long long offs )
+{
+	priv_fd_t *fdp;
+
+        DPRINTF("%s(%d, %lld)\n", __func__, fd, offs);
+	if (fd != -1) {
+		fdp = file_descriptors[fd];
+		
+		DPUSH( offs );
+		call_package( fdp->seek_xt, fdp->ih );
+		return ((((cell)POP()) >= 0)? 0 : -1);
+	} else {
+		return -1;
+	}
+}
+
+long long
+tell( int fd )
+{
+	priv_fd_t *fdp = file_descriptors[fd];
+	long long offs;
+
+	if( lookup_xt(fdp->ih, "tell", &fdp->tell_xt) )
+		return -1;
+	call_package( fdp->tell_xt, fdp->ih );
+	offs = DPOP();
+        DPRINTF("%s(%d) = %lld\n", __func__, fd, offs);
+	return offs;
+}
+
+int
+close_io( int fd )
+{
+	priv_fd_t *fdp;
+
+        DPRINTF("%s(%d)\n", __func__, fd);
+	if (fd != -1) {
+		fdp = file_descriptors[fd];
+
+		if( fdp->do_close )
+			close_dev( fdp->ih );
+		free( fdp );
+
+		file_descriptors[fd]=NULL;
+	}
+
+	return 0;
+}
diff --git a/roms/openbios/libc/extra.c b/roms/openbios/libc/extra.c
new file mode 100644
index 000000000..85731ade9
--- /dev/null
+++ b/roms/openbios/libc/extra.c
@@ -0,0 +1,49 @@
+/*
+ *   Creation Date: <2003/10/18 13:52:32 samuel>
+ *   Time-stamp: <2003/10/18 13:54:24 samuel>
+ *
+ *	<extra.c>
+ *
+ *	Libc extras
+ *
+ *   Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   version 2
+ *
+ */
+
+#include "config.h"
+#include "libc/string.h"
+#include "libc/vsprintf.h"
+#include "libopenbios/bindings.h"
+
+/* strncpy without 0-pad */
+char *
+strncpy_nopad( char *dest, const char *src, size_t n )
+{
+	int len = MIN( n, strlen(src)+1 );
+	return memcpy( dest, src, len );
+}
+
+/* printf */
+
+int forth_printf( const char *fmt, ... )
+{
+	char buf[512];
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i = vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+
+	PUSH(pointer2cell(buf));
+	PUSH(i);
+	fword("type");
+
+	return i;
+}
+
+
diff --git a/roms/openbios/libc/misc.c b/roms/openbios/libc/misc.c
new file mode 100644
index 000000000..e7cf4f408
--- /dev/null
+++ b/roms/openbios/libc/misc.c
@@ -0,0 +1,144 @@
+/*
+ *   Creation Date: <2002/10/19 21:05:07 samuel>
+ *   Time-stamp: <2002/10/22 22:29:18 samuel>
+ *
+ *	<misc.c>
+ *
+ *	Miscellaneous
+ *
+ *   Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libc/string.h"
+
+int errno_int;
+
+void
+qsort( void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void*) )
+{
+	unsigned int worked, i, j;
+
+	/* even more inefficient than the glibc variant :-) */
+	do {
+		char *p = base;
+		worked = 0;
+		for( i=0; i<nmemb-1; i++, p+= size ) {
+			if( compar( p, p + size ) > 0 ) {
+				worked = 1;
+				for( j=0; j<size; j++ ) {
+					char ch = p[j];
+					p[j] = p[j+size];
+					p[j+size] = ch;
+				}
+			}
+		}
+	} while( worked );
+}
+
+
+long int
+strtol( const char *nptr, char **endptr, int base )
+{
+	int sum, n, sign=1;
+	while( isspace(*nptr) )
+		nptr++;
+
+	if( *nptr == '-' || *nptr == '+' )
+		sign = (*nptr++ == '-') ? -1 : 1;
+
+	if( base == 16 || base == 0) {
+		if( !base )
+			base = (nptr[0] == '0')? 8 : 10;
+		if( nptr[0] == '0' && nptr[1] == 'x' ) {
+			nptr += 2;
+			base = 16;
+		}
+	}
+	for( sum=0 ;; nptr++ ) {
+		char ch = *nptr;
+		if( !isalnum(ch) )
+			break;
+		n = isdigit(ch) ? ch - '0' : toupper(ch) - 'A' + 10;
+		if( n >= base || n < 0 )
+			break;
+		sum *= base;
+		sum += n;
+	}
+	if( endptr )
+		*endptr = (char*)nptr;
+
+	return sum * sign;
+}
+
+long long int
+strtoll( const char *nptr, char **endptr, int base )
+{
+	long long int sum;
+	int n, sign=1;
+	while( isspace(*nptr) )
+		nptr++;
+
+	if( *nptr == '-' || *nptr == '+' )
+		sign = (*nptr++ == '-') ? -1 : 1;
+
+	if( base == 16 || base == 0) {
+		if( !base )
+			base = (nptr[0] == '0')? 8 : 10;
+		if( nptr[0] == '0' && nptr[1] == 'x' ) {
+			nptr += 2;
+			base = 16;
+		}
+	}
+	for( sum=0 ;; nptr++ ) {
+		char ch = *nptr;
+		if( !isalnum(ch) )
+			break;
+		n = isdigit(ch) ? ch - '0' : toupper(ch) - 'A' + 10;
+		if( n >= base || n < 0 )
+			break;
+		sum *= base;
+		sum += n;
+	}
+	if( endptr )
+		*endptr = (char*)nptr;
+
+	return sum * sign;
+}
+
+// Propolice support
+long __guard[8] = {
+#ifdef CONFIG_BIG_ENDIAN
+    (0 << 24) | (0 << 16) | ('\n' << 8) | 255,
+#else
+    (255 << 24) | ('\n' << 16) | (0 << 8) | 0,
+#endif
+    0, 0, 0, 0, 0, 0, 0
+};
+
+static void freeze(void)
+{
+    // Freeze
+    // XXX: Disable interrupts?
+    for(;;)
+        ;
+}
+
+void __stack_smash_handler(const char *func, int damaged)
+{
+    printk("Propolice detected a stack smashing attack %x at function %s,"
+           " freezing\n", damaged, func);
+    freeze();
+}
+
+void __stack_chk_fail(void)
+{
+    printk("Propolice detected a stack smashing attack, freezing\n");
+
+    freeze();
+}
diff --git a/roms/openbios/libc/string.c b/roms/openbios/libc/string.c
new file mode 100644
index 000000000..bde9a613a
--- /dev/null
+++ b/roms/openbios/libc/string.c
@@ -0,0 +1,384 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ *
+ * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
+ * -  Added strsep() which will replace strtok() soon (because strsep() is
+ *    reentrant and should be faster). Use only strsep() in new code, please.
+ */
+
+#include "config.h"
+#include "libc/string.h"
+#include "libc/stdlib.h"
+
+/**
+ * strnicmp - Case insensitive, length-limited string comparison
+ * @s1: One string
+ * @s2: The other string
+ * @len: the maximum number of characters to compare
+ */
+int strnicmp(const char *s1, const char *s2, size_t len)
+{
+	/* Yes, Virginia, it had better be unsigned */
+	unsigned char c1, c2;
+
+	c1 = 0;	c2 = 0;
+	if (len) {
+		do {
+			c1 = *s1; c2 = *s2;
+			s1++; s2++;
+			if (!c1)
+				break;
+			if (!c2)
+				break;
+			if (c1 == c2)
+				continue;
+			c1 = tolower(c1);
+			c2 = tolower(c2);
+			if (c1 != c2)
+				break;
+		} while (--len);
+	}
+	return (int)c1 - (int)c2;
+}
+
+/**
+ * strcpy - Copy a %NUL terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ */
+char * strcpy(char * dest,const char *src)
+{
+	char *tmp = dest;
+
+	while ((*dest++ = *src++) != '\0')
+		/* nothing */;
+	return tmp;
+}
+
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
+ * However, the result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ */
+char * strncpy(char * dest,const char *src,size_t count)
+{
+	char *tmp = dest;
+
+	while (count-- && (*dest++ = *src++) != '\0')
+		/* nothing */;
+
+	return tmp;
+}
+
+/**
+ * strcat - Append one %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ */
+char * strcat(char * dest, const char * src)
+{
+	char *tmp = dest;
+
+	while (*dest)
+		dest++;
+	while ((*dest++ = *src++) != '\0')
+		;
+
+	return tmp;
+}
+
+/**
+ * strncat - Append a length-limited, %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ * @count: The maximum numbers of bytes to copy
+ *
+ * Note that in contrast to strncpy, strncat ensures the result is
+ * terminated.
+ */
+char * strncat(char *dest, const char *src, size_t count)
+{
+	char *tmp = dest;
+
+	if (count) {
+		while (*dest)
+			dest++;
+		while ((*dest++ = *src++)) {
+			if (--count == 0) {
+				*dest = '\0';
+				break;
+			}
+		}
+	}
+
+	return tmp;
+}
+
+/**
+ * strcmp - Compare two strings
+ * @cs: One string
+ * @ct: Another string
+ */
+int strcmp(const char * cs,const char * ct)
+{
+	register signed char __res;
+
+	while (1) {
+		if ((__res = *cs - *ct++) != 0 || !*cs++)
+			break;
+	}
+
+	return __res;
+}
+
+/**
+ * strncmp - Compare two length-limited strings
+ * @cs: One string
+ * @ct: Another string
+ * @count: The maximum number of bytes to compare
+ */
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+	register signed char __res = 0;
+
+	while (count) {
+		if ((__res = *cs - *ct++) != 0 || !*cs++)
+			break;
+		count--;
+	}
+
+	return __res;
+}
+
+
+/**
+ * strchr - Find the first occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strchr(const char * s, int c)
+{
+	for(; *s != (char) c; ++s)
+		if (*s == '\0')
+			return NULL;
+	return (char *) s;
+}
+
+/**
+ * strrchr - Find the last occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strrchr(const char * s, int c)
+{
+       const char *p = s + strlen(s);
+       do {
+           if (*p == (char)c)
+               return (char *)p;
+       } while (--p >= s);
+       return NULL;
+}
+
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char * s)
+{
+	const char *sc;
+
+	for (sc = s; *sc != '\0'; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char * s, size_t count)
+{
+	const char *sc;
+
+	for (sc = s; count-- && *sc != '\0'; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+/**
+ * strpbrk - Find the first occurrence of a set of characters
+ * @cs: The string to be searched
+ * @ct: The characters to search for
+ */
+char * strpbrk(const char * cs,const char * ct)
+{
+	const char *sc1,*sc2;
+
+	for( sc1 = cs; *sc1 != '\0'; ++sc1) {
+		for( sc2 = ct; *sc2 != '\0'; ++sc2) {
+			if (*sc1 == *sc2)
+				return (char *) sc1;
+		}
+	}
+	return NULL;
+}
+
+/**
+ * strsep - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * strsep() updates @s to point after the token, ready for the next call.
+ *
+ * It returns empty tokens, too, behaving exactly like the libc function
+ * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
+ * Same semantics, slimmer shape. ;)
+ */
+char * strsep(char **s, const char *ct)
+{
+	char *sbegin = *s, *end;
+
+	if (sbegin == NULL)
+		return NULL;
+
+	end = strpbrk(sbegin, ct);
+	if (end)
+		*end++ = '\0';
+	*s = end;
+
+	return sbegin;
+}
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void * memset(void * s,int c,size_t count)
+{
+	char *xs = (char *) s;
+
+	while (count--)
+		*xs++ = c;
+
+	return s;
+}
+
+/**
+ * memcpy - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * You should not use this function to access IO space, use memcpy_toio()
+ * or memcpy_fromio() instead.
+ */
+void * memcpy(void * dest,const void *src,size_t count)
+{
+	char *tmp = (char *) dest, *s = (char *) src;
+
+	while (count--)
+		*tmp++ = *s++;
+
+	return dest;
+}
+
+/**
+ * memmove - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * Unlike memcpy(), memmove() copes with overlapping areas.
+ */
+void * memmove(void * dest,const void *src,size_t count)
+{
+	char *tmp, *s;
+
+	if (dest <= src) {
+		tmp = (char *) dest;
+		s = (char *) src;
+		while (count--)
+			*tmp++ = *s++;
+		}
+	else {
+		tmp = (char *) dest + count;
+		s = (char *) src + count;
+		while (count--)
+			*--tmp = *--s;
+		}
+
+	return dest;
+}
+
+/**
+ * memcmp - Compare two areas of memory
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ */
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+	const unsigned char *su1, *su2;
+	int res = 0;
+
+	for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+		if ((res = *su1 - *su2) != 0)
+			break;
+	return res;
+}
+
+char *
+strdup( const char *str )
+{
+	char *p = malloc( strlen(str) + 1 );
+	strcpy( p, str );
+	return p;
+}
+
+int
+strcasecmp( const char *cs, const char *ct )
+{
+	register signed char __res;
+
+	while (1) {
+		char ch1 = toupper(*cs), ch2 = toupper(*ct);
+		ct++;
+		if ((__res = ch1 - ch2) != 0 || !*cs++)
+			break;
+	}
+	return __res;
+}
+
+int
+strncasecmp( const char *cs, const char *ct, size_t count )
+{
+	register signed char __res = 0;
+
+	while (count--) {
+		char ch1 = toupper(*cs), ch2 = toupper(*ct);
+		ct++;
+		if ((__res = ch1 - ch2) != 0 || !*cs++)
+			break;
+	}
+	return __res;
+}
+
diff --git a/roms/openbios/libc/vsprintf.c b/roms/openbios/libc/vsprintf.c
new file mode 100644
index 000000000..29ec7b96e
--- /dev/null
+++ b/roms/openbios/libc/vsprintf.c
@@ -0,0 +1,448 @@
+/*
+ * String functions for logger.
+ */
+
+/*
+ *  linux/lib/vsprintf.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+/*
+ * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
+ * - changed to provide snprintf and vsnprintf functions
+ */
+
+#include "config.h"
+#include "libc/string.h"
+#include "libc/vsprintf.h"
+
+static int skip_atoi(const char **s)
+{
+	int i=0;
+
+	while (isdigit(**s))
+		i = i*10 + *((*s)++) - '0';
+	return i;
+}
+
+#define ZEROPAD	1		/* pad with zero */
+#define SIGN	2		/* unsigned/signed long */
+#define PLUS	4		/* show plus */
+#define SPACE	8		/* space if plus */
+#define LEFT	16		/* left justified */
+#define SPECIAL	32		/* 0x */
+#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long long) n) % (unsigned) base; \
+n = ((unsigned long long) n) / (unsigned) base; \
+__res; })
+
+static int mstrlen( const char *str );
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
+{
+	char c,sign,tmp[66];
+	const char *digits;
+	static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+	static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+	int i;
+
+	digits = (type & LARGE) ? large_digits : small_digits;
+	if (type & LEFT)
+		type &= ~ZEROPAD;
+	if (base < 2 || base > 36)
+                return NULL;
+	c = (type & ZEROPAD) ? '0' : ' ';
+	sign = 0;
+	if (type & SIGN) {
+		if (num < 0) {
+			sign = '-';
+			num = -num;
+			size--;
+		} else if (type & PLUS) {
+			sign = '+';
+			size--;
+		} else if (type & SPACE) {
+			sign = ' ';
+			size--;
+		}
+	}
+	if (type & SPECIAL) {
+		if (base == 16)
+			size -= 2;
+		else if (base == 8)
+			size--;
+	}
+	i = 0;
+	if (num == 0)
+		tmp[i++]='0';
+	else while (num != 0)
+		tmp[i++] = digits[do_div(num,base)];
+	if (i > precision)
+		precision = i;
+	size -= precision;
+	if (!(type&(ZEROPAD+LEFT))) {
+		while(size-->0) {
+			if (buf <= end)
+				*buf = ' ';
+			++buf;
+		}
+	}
+	if (sign) {
+		if (buf <= end)
+			*buf = sign;
+		++buf;
+	}
+	if (type & SPECIAL) {
+		if (base==8) {
+			if (buf <= end)
+				*buf = '0';
+			++buf;
+		} else if (base==16) {
+			if (buf <= end)
+				*buf = '0';
+			++buf;
+			if (buf <= end)
+				*buf = digits[33];
+			++buf;
+		}
+	}
+	if (!(type & LEFT)) {
+		while (size-- > 0) {
+			if (buf <= end)
+				*buf = c;
+			++buf;
+		}
+	}
+	while (i < precision--) {
+		if (buf <= end)
+			*buf = '0';
+		++buf;
+	}
+	while (i-- > 0) {
+		if (buf <= end)
+			*buf = tmp[i];
+		++buf;
+	}
+	while (size-- > 0) {
+		if (buf <= end)
+			*buf = ' ';
+		++buf;
+	}
+	return buf;
+}
+
+/**
+* vsnprintf - Format a string and place it in a buffer
+* @buf: The buffer to place the result into
+* @size: The size of the buffer, including the trailing null space
+* @fmt: The format string to use
+* @args: Arguments for the format string
+*
+* Call this function if you are already dealing with a va_list.
+* You probably want snprintf instead.
+ */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+	int len;
+	unsigned long long num;
+	int i, base;
+	char *str, *end, c;
+	const char *s;
+
+	int flags;		/* flags to number() */
+
+	int field_width;	/* width of output field */
+	int precision;		/* min. # of digits for integers; max
+				   number of chars for from string */
+	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
+				/* 'z' support added 23/7/1999 S.H.    */
+				/* 'z' changed to 'Z' --davidm 1/25/99 */
+
+	str = buf;
+	end = buf + size - 1;
+
+	if (end < buf - 1) {
+		end = ((void *) -1);
+		size = end - buf + 1;
+	}
+
+	for (; *fmt ; ++fmt) {
+		if (*fmt != '%') {
+			if (str <= end)
+				*str = *fmt;
+			++str;
+			continue;
+		}
+
+		/* process flags */
+		flags = 0;
+		repeat:
+			++fmt;		/* this also skips first '%' */
+			switch (*fmt) {
+				case '-': flags |= LEFT; goto repeat;
+				case '+': flags |= PLUS; goto repeat;
+				case ' ': flags |= SPACE; goto repeat;
+				case '#': flags |= SPECIAL; goto repeat;
+				case '0': flags |= ZEROPAD; goto repeat;
+			}
+
+		/* get field width */
+		field_width = -1;
+		if (isdigit(*fmt))
+			field_width = skip_atoi(&fmt);
+		else if (*fmt == '*') {
+			++fmt;
+			/* it's the next argument */
+			field_width = va_arg(args, int);
+			if (field_width < 0) {
+				field_width = -field_width;
+				flags |= LEFT;
+			}
+		}
+
+		/* get the precision */
+		precision = -1;
+		if (*fmt == '.') {
+			++fmt;
+			if (isdigit(*fmt))
+				precision = skip_atoi(&fmt);
+			else if (*fmt == '*') {
+				++fmt;
+				/* it's the next argument */
+				precision = va_arg(args, int);
+			}
+			if (precision < 0)
+				precision = 0;
+		}
+
+		/* get the conversion qualifier */
+		qualifier = -1;
+		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+		    *fmt =='Z' || *fmt == 'z') {
+			qualifier = *fmt;
+			++fmt;
+			if (qualifier == 'l' && *fmt == 'l') {
+				qualifier = 'L';
+				++fmt;
+			}
+		}
+
+		/* default base */
+		base = 10;
+
+		switch (*fmt) {
+			case 'c':
+				if (!(flags & LEFT)) {
+					while (--field_width > 0) {
+						if (str <= end)
+							*str = ' ';
+						++str;
+					}
+				}
+				c = (unsigned char) va_arg(args, int);
+				if (str <= end)
+					*str = c;
+				++str;
+				while (--field_width > 0) {
+					if (str <= end)
+						*str = ' ';
+					++str;
+				}
+				continue;
+
+			case 's':
+				s = va_arg(args, char *);
+				if ((unsigned long)s < PAGE_SIZE)
+					s = "<NULL>";
+
+#if 0
+                                len = strnlen(s, precision);
+#else
+                                len = mstrlen(s);
+                                if( precision > len )
+                                    len = precision;
+#endif
+				if (!(flags & LEFT)) {
+					while (len < field_width--) {
+						if (str <= end)
+							*str = ' ';
+						++str;
+					}
+				}
+				for (i = 0; i < len; ++i) {
+					if (str <= end)
+						*str = *s;
+					++str; ++s;
+				}
+				while (len < field_width--) {
+					if (str <= end)
+						*str = ' ';
+					++str;
+				}
+				continue;
+
+			case 'p':
+				if (field_width == -1) {
+					field_width = 2*sizeof(void *);
+					flags |= ZEROPAD;
+				}
+				str = number(str, end,
+						(unsigned long) va_arg(args, void *),
+						16, field_width, precision, flags);
+				continue;
+
+
+			case 'n':
+				/* FIXME:
+				* What does C99 say about the overflow case here? */
+				if (qualifier == 'l') {
+					long * ip = va_arg(args, long *);
+					*ip = (str - buf);
+				} else if (qualifier == 'Z' || qualifier == 'z') {
+					size_t * ip = va_arg(args, size_t *);
+					*ip = (str - buf);
+				} else {
+					int * ip = va_arg(args, int *);
+					*ip = (str - buf);
+				}
+				continue;
+
+			case '%':
+				if (str <= end)
+					*str = '%';
+				++str;
+				continue;
+
+				/* integer number formats - set up the flags and "break" */
+			case 'o':
+				base = 8;
+				break;
+
+			case 'X':
+				flags |= LARGE;
+			case 'x':
+				base = 16;
+				break;
+
+			case 'd':
+			case 'i':
+				flags |= SIGN;
+			case 'u':
+				break;
+
+			default:
+				if (str <= end)
+					*str = '%';
+				++str;
+				if (*fmt) {
+					if (str <= end)
+						*str = *fmt;
+					++str;
+				} else {
+					--fmt;
+				}
+				continue;
+		}
+		if (qualifier == 'L')
+			num = va_arg(args, long long);
+		else if (qualifier == 'l') {
+			num = va_arg(args, unsigned long);
+			if (flags & SIGN)
+				num = (signed long) num;
+		} else if (qualifier == 'Z' || qualifier == 'z') {
+			num = va_arg(args, size_t);
+		} else if (qualifier == 'h') {
+			num = (unsigned short) va_arg(args, int);
+			if (flags & SIGN)
+				num = (signed short) num;
+		} else {
+			num = va_arg(args, unsigned int);
+			if (flags & SIGN)
+				num = (signed int) num;
+		}
+		str = number(str, end, num, base,
+				field_width, precision, flags);
+	}
+	if (str <= end)
+		*str = '\0';
+	else if (size > 0)
+		/* don't write out a null byte if the buf size is zero */
+		*end = '\0';
+	/* the trailing null byte doesn't count towards the total
+	* ++str;
+	*/
+	return str-buf;
+}
+
+/**
+ * snprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i=vsnprintf(buf,size,fmt,args);
+	va_end(args);
+	return i;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+	return vsnprintf(buf, (~0U)>>1, fmt, args);
+}
+
+
+/**
+ * sprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int sprintf(char * buf, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i=vsprintf(buf,fmt,args);
+	va_end(args);
+	return i;
+}
+
+static int mstrlen( const char *str )
+{
+	int i=0;
+	if( str == NULL )
+		return 0;
+	while( *str++ )
+		i++;
+	return i;
+}
-- 
cgit