aboutsummaryrefslogtreecommitdiffstats
path: root/roms/openbios/libc
diff options
context:
space:
mode:
authorfishsoupisgood <github@madingley.org>2019-04-29 01:17:54 +0100
committerfishsoupisgood <github@madingley.org>2019-05-27 03:43:43 +0100
commit3f2546b2ef55b661fd8dd69682b38992225e86f6 (patch)
tree65ca85f13617aee1dce474596800950f266a456c /roms/openbios/libc
downloadqemu-master.tar.gz
qemu-master.tar.bz2
qemu-master.zip
Initial import of qemu-2.4.1HEADmaster
Diffstat (limited to 'roms/openbios/libc')
-rw-r--r--roms/openbios/libc/build.xml12
-rw-r--r--roms/openbios/libc/ctype.c34
-rw-r--r--roms/openbios/libc/diskio.c248
-rw-r--r--roms/openbios/libc/extra.c49
-rw-r--r--roms/openbios/libc/misc.c144
-rw-r--r--roms/openbios/libc/string.c387
-rw-r--r--roms/openbios/libc/vsprintf.c448
7 files changed, 1322 insertions, 0 deletions
diff --git a/roms/openbios/libc/build.xml b/roms/openbios/libc/build.xml
new file mode 100644
index 00000000..cb2b560d
--- /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 00000000..c433f6c6
--- /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 00000000..23f38ebb
--- /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 00000000..85731ade
--- /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 00000000..e7cf4f40
--- /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 00000000..8f62bd7b
--- /dev/null
+++ b/roms/openbios/libc/string.c
@@ -0,0 +1,387 @@
+/*
+ * 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;
+ if( !str )
+ return NULL;
+ 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 00000000..29ec7b96
--- /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;
+}