Merge branch 'master' of /home/wd/git/u-boot/custodians
diff --git a/Makefile b/Makefile
index 47db5b7..0e94875 100644
--- a/Makefile
+++ b/Makefile
@@ -243,6 +243,9 @@
 	"post/board/$(BOARDDIR)/libpost$(BOARD).a"; fi)
 LIBS += common/libcommon.a
 LIBS += libfdt/libfdt.a
+ifeq ($(CONFIG_API),y)
+LIBS += api/libapi.a
+endif
 
 LIBS := $(addprefix $(obj),$(LIBS))
 .PHONY : $(LIBS)
@@ -255,6 +258,10 @@
 SUBDIRS	= tools \
 	  examples
 
+ifeq ($(CONFIG_API),y)
+SUBDIRS += api_examples
+endif
+
 .PHONY : $(SUBDIRS)
 
 ifeq ($(CONFIG_NAND_U_BOOT),y)
@@ -2749,6 +2756,7 @@
 	rm -f $(obj)board/bf537-stamp/u-boot.lds $(obj)board/bf561-ezkit/u-boot.lds
 	rm -f $(obj)include/bmp_logo.h
 	rm -f $(obj)nand_spl/u-boot-spl $(obj)nand_spl/u-boot-spl.map
+	rm -f $(obj)api_examples/demo
 
 clobber:	clean
 	find $(OBJTREE) -type f \( -name .depend \
@@ -2762,6 +2770,8 @@
 	rm -f $(obj)tools/inca-swap-bytes $(obj)cpu/mpc824x/bedbug_603e.c
 	rm -f $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
 	[ ! -d $(OBJTREE)/nand_spl ] || find $(obj)nand_spl -lname "*" -print | xargs rm -f
+	find $(obj)api_examples -lname "*" -print | xargs rm -f
+	rm -f $(obj)api_examples/demo
 
 ifeq ($(OBJTREE),$(SRCTREE))
 mrproper \
diff --git a/api/Makefile b/api/Makefile
new file mode 100644
index 0000000..94de3dc
--- /dev/null
+++ b/api/Makefile
@@ -0,0 +1,40 @@
+#
+# (C) Copyright 2007 Semihalf
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 Foundatio; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)libapi.a
+
+COBJS	= api.o api_net.o api_storage.o api_platform-$(ARCH).o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
diff --git a/api/README b/api/README
new file mode 100644
index 0000000..c8f9c45
--- /dev/null
+++ b/api/README
@@ -0,0 +1,55 @@
+U-Boot machine/arch independent API for external apps
+=====================================================
+
+1.  Main assumptions
+
+  - there is a single entry point (syscall) to the API
+
+  - per current design the syscall is a C-callable function in the U-Boot
+    text, which might evolve into a real syscall using machine exception trap
+    once this initial version proves functional
+
+  - the consumer app is responsible for producing appropriate context (call
+    number and arguments)
+
+  - upon entry, the syscall dispatches the call to other (existing) U-Boot
+    functional areas like networking or storage operations
+
+  - consumer application will recognize the API is available by searching
+    a specified (assumed by convention) range of address space for the
+    signature
+
+  - the U-Boot integral part of the API is meant to be thin and non-intrusive,
+    leaving as much processing as possible on the consumer application side,
+    for example it doesn't keep states, but relies on hints from the app and
+    so on 
+
+  - optional (CONFIG_API)
+
+
+2. Calls
+
+  - console related (getc, putc, tstc etc.)
+  - system (reset, platform info)
+  - time (delay, current)
+  - env vars (enumerate all, get, set)
+  - devices (enumerate all, open, close, read, write); currently two classes
+    of devices are recognized and supported: network and storage (ide, scsi,
+    usb etc.)
+
+
+3. Structure overview
+
+  - core API, integral part of U-Boot, mandatory
+    - implements the single entry point (mimics UNIX syscall)
+
+  - glue
+    - entry point at the consumer side, allows to make syscall, mandatory
+      part
+
+    - helper conveniency wrappers so that consumer app does not have to use
+      the syscall directly, but in a more friendly manner (a la libc calls),
+      optional part
+
+  - consumer application
+    - calls directly, or leverages the provided glue mid-layer
diff --git a/api/api.c b/api/api.c
new file mode 100644
index 0000000..10f83eb
--- /dev/null
+++ b/api/api.c
@@ -0,0 +1,670 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_API)
+
+#include <command.h>
+#include <common.h>
+#include <malloc.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+#include "api_private.h"
+
+#define DEBUG
+#undef DEBUG
+
+/* U-Boot routines needed */
+extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+extern uchar (*env_get_char)(int);
+extern uchar *env_get_addr(int);
+
+/*****************************************************************************
+ *
+ * This is the API core.
+ *
+ * API_ functions are part of U-Boot code and constitute the lowest level
+ * calls:
+ *
+ *  - they know what values they need as arguments
+ *  - their direct return value pertains to the API_ "shell" itself (0 on
+ *    success, some error code otherwise)
+ *  - if the call returns a value it is buried within arguments
+ *
+ ****************************************************************************/
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+typedef	int (*cfp_t)(va_list argp);
+
+static int calls_no;
+
+/*
+ * pseudo signature:
+ *
+ * int API_getc(int *c)
+ */
+static int API_getc(va_list ap)
+{
+	int *c;
+
+	if ((c = (int *)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+
+	*c = getc();
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_tstc(int *c)
+ */
+static int API_tstc(va_list ap)
+{
+	int *t;
+
+	if ((t = (int *)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+
+	*t = tstc();
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_putc(char *ch)
+ */
+static int API_putc(va_list ap)
+{
+	char *c;
+
+	if ((c = (char *)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+
+	putc(*c);
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_puts(char **s)
+ */
+static int API_puts(va_list ap)
+{
+	char *s;
+
+	if ((s = (char *)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+
+	puts(s);
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_reset(void)
+ */
+static int API_reset(va_list ap)
+{
+	do_reset(NULL, 0, 0, NULL);
+
+	/* NOT REACHED */
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_get_sys_info(struct sys_info *si)
+ *
+ * fill out the sys_info struct containing selected parameters about the
+ * machine
+ */
+static int API_get_sys_info(va_list ap)
+{
+	struct sys_info *si;
+
+	si = (struct sys_info *)va_arg(ap, u_int32_t);
+	if (si == NULL)
+		return API_ENOMEM;
+
+	return (platform_sys_info(si)) ? 0 : API_ENODEV;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_udelay(unsigned long *udelay)
+ */
+static int API_udelay(va_list ap)
+{
+	unsigned long *d;
+
+	if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+
+	udelay(*d);
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_get_timer(unsigned long *current, unsigned long *base)
+ */
+static int API_get_timer(va_list ap)
+{
+	unsigned long *base, *cur;
+
+	cur = (unsigned long *)va_arg(ap, u_int32_t);
+	if (cur == NULL)
+		return API_EINVAL;
+
+	base = (unsigned long *)va_arg(ap, u_int32_t);
+	if (base == NULL)
+		return API_EINVAL;
+
+	*cur = get_timer(*base);
+	return 0;
+}
+
+
+/*****************************************************************************
+ *
+ * pseudo signature:
+ *
+ * int API_dev_enum(struct device_info *)
+ *
+ *
+ * cookies uniqely identify the previously enumerated device instance and
+ * provide a hint for what to inspect in current enum iteration:
+ *
+ *   - net: &eth_device struct address from list pointed to by eth_devices
+ *
+ *   - storage: block_dev_desc_t struct address from &ide_dev_desc[n],
+ *     &scsi_dev_desc[n] and similar tables
+ *
+ ****************************************************************************/
+
+static int API_dev_enum(va_list ap)
+{
+	struct device_info *di;
+
+	/* arg is ptr to the device_info struct we are going to fill out */
+	di = (struct device_info *)va_arg(ap, u_int32_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	if (di->cookie == NULL) {
+		/* start over - clean up enumeration */
+		dev_enum_reset();	/* XXX shouldn't the name contain 'stor'? */
+		debugf("RESTART ENUM\n");
+		
+		/* net device enumeration first */
+		if (dev_enum_net(di))
+			return 0;
+	}
+
+	/*
+	 * The hidden assumption is there can only be one active network
+	 * device and it is identified upon enumeration (re)start, so there's
+	 * no point in trying to find network devices in other cases than the
+	 * (re)start and hence the 'next' device can only be storage
+	 */
+	if (!dev_enum_storage(di))
+		/* make sure we mark there are no more devices */
+		di->cookie = NULL;
+
+	return 0;
+}
+
+
+static int API_dev_open(va_list ap)
+{
+	struct device_info *di;
+	int err = 0;
+
+	/* arg is ptr to the device_info struct */
+	di = (struct device_info *)va_arg(ap, u_int32_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	/* Allow only one consumer of the device at a time */
+	if (di->state == DEV_STA_OPEN)
+		return API_EBUSY;
+
+	if (di->cookie == NULL)
+		return API_ENODEV;
+
+	if (di->type & DEV_TYP_STOR)
+		err = dev_open_stor(di->cookie);
+
+	else if (di->type & DEV_TYP_NET)
+		err = dev_open_net(di->cookie);
+	else
+		err = API_ENODEV;
+
+	if (!err)
+		di->state = DEV_STA_OPEN;
+
+	return err;
+}
+
+
+static int API_dev_close(va_list ap)
+{
+	struct device_info *di;
+	int err = 0;
+
+	/* arg is ptr to the device_info struct */
+	di = (struct device_info *)va_arg(ap, u_int32_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	if (di->state == DEV_STA_CLOSED)
+		return 0;
+
+	if (di->cookie == NULL)
+		return API_ENODEV;
+
+	if (di->type & DEV_TYP_STOR)
+		err = dev_close_stor(di->cookie);
+
+	else if (di->type & DEV_TYP_NET)
+		err = dev_close_net(di->cookie);
+	else
+		/*
+		 * In case of unknown device we cannot change its state, so
+		 * only return error code
+		 */
+		err = API_ENODEV;
+
+	if (!err)
+		di->state = DEV_STA_CLOSED;
+
+	return err;
+}
+
+
+/*
+ * Notice: this is for sending network packets only, as U-Boot does not
+ * support writing to storage at the moment (12.2007)
+ *
+ * pseudo signature:
+ *
+ * int API_dev_write(
+ *	struct device_info *di,
+ *	void *buf,
+ *	int *len
+ * )
+ *
+ * buf:	ptr to buffer from where to get the data to send
+ *
+ * len: length of packet to be sent (in bytes)
+ *
+ */
+static int API_dev_write(va_list ap)
+{
+	struct device_info *di;
+	void *buf;
+	int *len;
+	int err = 0;
+
+	/* 1. arg is ptr to the device_info struct */
+	di = (struct device_info *)va_arg(ap, u_int32_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	/* XXX should we check if device is open? i.e. the ->state ? */
+
+	if (di->cookie == NULL)
+		return API_ENODEV;
+
+	/* 2. arg is ptr to buffer from where to get data to write */
+	buf = (void *)va_arg(ap, u_int32_t);
+	if (buf == NULL)
+		return API_EINVAL;
+
+	/* 3. arg is length of buffer */
+	len = (int *)va_arg(ap, u_int32_t);
+	if (len == NULL)
+		return API_EINVAL;
+	if (*len <= 0)
+		return API_EINVAL;
+
+	if (di->type & DEV_TYP_STOR)
+		/* 
+		 * write to storage is currently not supported by U-Boot:
+		 * no storage device implements block_write() method
+		 */
+		return API_ENODEV;
+
+	else if (di->type & DEV_TYP_NET)
+		err = dev_write_net(di->cookie, buf, *len);
+	else
+		err = API_ENODEV;
+
+	return err;
+}
+
+
+/*
+ * pseudo signature:
+ *
+ * int API_dev_read(
+ *	struct device_info *di,
+ *	void *buf,
+ *	size_t *len,
+ *	unsigned long *start
+ *	size_t *act_len
+ * )
+ *
+ * buf:	ptr to buffer where to put the read data
+ *
+ * len: ptr to length to be read
+ *      - network: len of packet to read (in bytes)
+ *      - storage: # of blocks to read (can vary in size depending on define)
+ *
+ * start: ptr to start block (only used for storage devices, ignored for
+ *        network)
+ *
+ * act_len: ptr to where to put the len actually read
+ */
+static int API_dev_read(va_list ap)
+{
+	struct device_info *di;
+	void *buf;
+	lbasize_t *len_stor, *act_len_stor;
+	lbastart_t *start;
+	int *len_net, *act_len_net;
+
+	/* 1. arg is ptr to the device_info struct */
+	di = (struct device_info *)va_arg(ap, u_int32_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	/* XXX should we check if device is open? i.e. the ->state ? */
+
+	if (di->cookie == NULL)
+		return API_ENODEV;
+
+	/* 2. arg is ptr to buffer from where to put the read data */
+	buf = (void *)va_arg(ap, u_int32_t);
+	if (buf == NULL)
+		return API_EINVAL;
+
+	if (di->type & DEV_TYP_STOR) {
+		/* 3. arg - ptr to var with # of blocks to read */
+		len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
+		if (!len_stor)
+			return API_EINVAL;
+		if (*len_stor <= 0)
+			return API_EINVAL;
+
+		/* 4. arg - ptr to var with start block */
+		start = (lbastart_t *)va_arg(ap, u_int32_t);
+
+		/* 5. arg - ptr to var where to put the len actually read */
+		act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
+		if (!act_len_stor)
+			return API_EINVAL;
+
+		*act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
+
+	} else if (di->type & DEV_TYP_NET) {
+
+		/* 3. arg points to the var with length of packet to read */
+		len_net = (int *)va_arg(ap, u_int32_t);
+		if (!len_net)
+			return API_EINVAL;
+		if (*len_net <= 0)
+			return API_EINVAL;
+
+		/* 4. - ptr to var where to put the len actually read */
+		act_len_net = (int *)va_arg(ap, u_int32_t);
+		if (!act_len_net)
+			return API_EINVAL;
+
+		*act_len_net = dev_read_net(di->cookie, buf, *len_net);
+
+	} else
+		return API_ENODEV;
+
+	return 0;
+}
+
+
+/*
+ * pseudo signature:
+ *
+ * int API_env_get(const char *name, char **value)
+ *
+ * name: ptr to name of env var
+ */
+static int API_env_get(va_list ap)
+{
+	char *name, **value;
+
+	if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+	if ((value = (char **)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+
+	*value = getenv(name);
+
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_env_set(const char *name, const char *value)
+ *
+ * name: ptr to name of env var
+ *
+ * value: ptr to value to be set
+ */
+static int API_env_set(va_list ap)
+{
+	char *name, *value;
+
+	if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+	if ((value = (char *)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+
+	setenv(name, value);
+
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_env_enum(const char *last, char **next)
+ *
+ * last: ptr to name of env var found in last iteration
+ */
+static int API_env_enum(va_list ap)
+{
+	int i, n;
+	char *last, **next;
+
+	last = (char *)va_arg(ap, u_int32_t);
+	
+	if ((next = (char **)va_arg(ap, u_int32_t)) == NULL)
+		return API_EINVAL;
+
+	if (last == NULL)
+		/* start over */
+		*next = ((char *)env_get_addr(0));
+	else {
+		*next = last;
+
+		for (i = 0; env_get_char(i) != '\0'; i = n + 1) {
+			for (n = i; env_get_char(n) != '\0'; ++n) {
+				if (n >= CFG_ENV_SIZE) {
+					/* XXX shouldn't we set *next = NULL?? */
+					return 0;
+				}
+			}
+		
+			if (envmatch((uchar *)last, i) < 0)
+				continue;
+
+			/* try to get next name */
+			i = n + 1;
+			if (env_get_char(i) == '\0') {
+				/* no more left */
+				*next = NULL;
+				return 0;
+			}
+
+			*next = ((char *)env_get_addr(i));
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static cfp_t calls_table[API_MAXCALL] = { NULL, };
+
+/*
+ * The main syscall entry point - this is not reentrant, only one call is
+ * serviced until finished.
+ *
+ * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
+ * 
+ * call:	syscall number
+ *
+ * retval:	points to the return value placeholder, this is the place the
+ *		syscall puts its return value, if NULL the caller does not
+ *		expect a return value
+ *
+ * ...		syscall arguments (variable number)
+ *
+ * returns:	0 if the call not found, 1 if serviced
+ */
+int syscall(int call, int *retval, ...)
+{
+	va_list	ap;
+	int rv;
+
+	if (call < 0 || call >= calls_no || calls_table[call] == NULL) {
+		debugf("invalid call #%d\n", call);
+		return 0;
+	}
+
+	if (calls_table[call] == NULL) {
+		debugf("syscall #%d does not have a handler\n", call);
+		return 0;
+	}
+
+	va_start(ap, retval);
+	rv = calls_table[call](ap);
+	if (retval != NULL)
+		*retval = rv;
+
+	return 1;
+}
+
+void api_init(void)
+{
+	struct api_signature *sig = NULL;
+
+	/* TODO put this into linker set one day... */
+	calls_table[API_RSVD] = NULL;
+	calls_table[API_GETC] = &API_getc;
+	calls_table[API_PUTC] = &API_putc;
+	calls_table[API_TSTC] = &API_tstc;
+	calls_table[API_PUTS] = &API_puts;
+	calls_table[API_RESET] = &API_reset;
+	calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
+	calls_table[API_UDELAY] = &API_udelay;
+	calls_table[API_GET_TIMER] = &API_get_timer;
+	calls_table[API_DEV_ENUM] = &API_dev_enum;
+	calls_table[API_DEV_OPEN] = &API_dev_open;
+	calls_table[API_DEV_CLOSE] = &API_dev_close;
+	calls_table[API_DEV_READ] = &API_dev_read;
+	calls_table[API_DEV_WRITE] = &API_dev_write;
+	calls_table[API_ENV_GET] = &API_env_get;
+	calls_table[API_ENV_SET] = &API_env_set;
+	calls_table[API_ENV_ENUM] = &API_env_enum;
+	calls_no = API_MAXCALL;
+
+	debugf("API initialized with %d calls\n", calls_no);
+
+	dev_stor_init();
+
+	/*
+	 * Produce the signature so the API consumers can find it
+	 */
+	sig = malloc(sizeof(struct api_signature));
+	if (sig == NULL) {
+		printf("API: could not allocate memory for the signature!\n");
+		return;
+	}
+
+	debugf("API sig @ 0x%08x\n", sig);
+	memcpy(sig->magic, API_SIG_MAGIC, 8);
+	sig->version = API_SIG_VERSION;
+	sig->syscall = &syscall;
+	sig->checksum = 0;
+	sig->checksum = crc32(0, (unsigned char *)sig,
+			      sizeof(struct api_signature));
+	debugf("syscall entry: 0x%08x\n", sig->syscall);
+}
+
+void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
+			int flags)
+{
+	int i;
+
+	if (!si->mr || !size || (flags == 0))
+		return;
+	
+	/* find free slot */
+	for (i = 0; i < si->mr_no; i++)
+		if (si->mr[i].flags == 0) {
+			/* insert new mem region */
+			si->mr[i].start = start;
+			si->mr[i].size = size;
+			si->mr[i].flags = flags;
+			return;
+		}
+}
+
+#endif /* CONFIG_API */
diff --git a/api/api_net.c b/api/api_net.c
new file mode 100644
index 0000000..9b20a17
--- /dev/null
+++ b/api/api_net.c
@@ -0,0 +1,113 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_API)
+
+#include <common.h>
+#include <net.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DEBUG
+#undef DEBUG
+
+#if !defined(CONFIG_NET_MULTI)
+#error "API/net is currently only available for platforms with CONFIG_NET_MULTI"
+#endif
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+#define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0)
+
+
+static int dev_valid_net(void *cookie)
+{
+	return ((void *)eth_get_dev() == cookie) ? 1 : 0;
+}
+
+int dev_open_net(void *cookie)
+{
+	if (!dev_valid_net(cookie))
+		return API_ENODEV;
+
+	if (eth_init(gd->bd) < 0)
+		return API_EIO;
+
+	return 0;
+}
+
+int dev_close_net(void *cookie)
+{
+	if (!dev_valid_net(cookie))
+		return API_ENODEV;
+
+	eth_halt();
+	return 0;
+}
+
+/* 
+ * There can only be one active eth interface at a time - use what is
+ * currently set to eth_current
+ */
+int dev_enum_net(struct device_info *di)
+{
+	struct eth_device *eth_current = eth_get_dev();
+
+	di->type = DEV_TYP_NET;
+	di->cookie = (void *)eth_current;
+	if (di->cookie == NULL)
+		return 0;
+
+	memcpy(di->di_net.hwaddr, eth_current->enetaddr, 6);
+
+	debugf("device found, returning cookie 0x%08x\n",
+		(u_int32_t)di->cookie);
+
+	return 1;
+}
+
+int dev_write_net(void *cookie, void *buf, int len)
+{
+	/* XXX verify that cookie points to a valid net device??? */
+
+	return eth_send(buf, len);
+}
+
+int dev_read_net(void *cookie, void *buf, int len)
+{
+	/* XXX verify that cookie points to a valid net device??? */
+
+	return eth_receive(buf, len);
+}
+
+#endif /* CONFIG_API */
diff --git a/api/api_platform-arm.c b/api/api_platform-arm.c
new file mode 100644
index 0000000..ca15ca5
--- /dev/null
+++ b/api/api_platform-arm.c
@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * This file contains routines that fetch data from ARM-dependent sources
+ * (bd_info etc.)
+ *
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_API)
+
+#include <linux/types.h>
+#include <api_public.h>
+
+#include <asm/u-boot.h>
+#include <asm/global_data.h>
+
+#include "api_private.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Important notice: handling of individual fields MUST be kept in sync with
+ * include/asm-arm/u-boot.h and include/asm-arm/global_data.h, so any changes
+ * need to reflect their current state and layout of structures involved!
+ */
+int platform_sys_info(struct sys_info *si)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
+		platform_set_mr(si, gd->bd->bi_dram[i].start,
+				gd->bd->bi_dram[i].size, MR_ATTR_DRAM);
+
+	return 1;
+}
+
+#endif /* CONFIG_API */
diff --git a/api/api_platform-ppc.c b/api/api_platform-ppc.c
new file mode 100644
index 0000000..ca9f9a5
--- /dev/null
+++ b/api/api_platform-ppc.c
@@ -0,0 +1,79 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * This file contains routines that fetch data from PowerPC-dependent sources
+ * (bd_info etc.)
+ *
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_API)
+
+#include <linux/types.h>
+#include <api_public.h>
+
+#include <asm/u-boot.h>
+#include <asm/global_data.h>
+
+#include "api_private.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Important notice: handling of individual fields MUST be kept in sync with
+ * include/asm-ppc/u-boot.h and include/asm-ppc/global_data.h, so any changes
+ * need to reflect their current state and layout of structures involved!
+ */
+int platform_sys_info(struct sys_info *si)
+{
+	si->clk_bus = gd->bus_clk;
+	si->clk_cpu = gd->cpu_clk;
+
+#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) || \
+    defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+#define bi_bar	bi_immr_base
+#elif defined(CONFIG_MPC5xxx)
+#define bi_bar	bi_mbar_base
+#elif defined(CONFIG_MPC83XX)
+#define bi_bar	bi_immrbar
+#elif defined(CONFIG_MPC8220)
+#define bi_bar	bi_mbar_base
+#endif
+
+#if defined(bi_bar)
+	si->bar = gd->bd->bi_bar;
+#undef bi_bar
+#else
+	si->bar = NULL;
+#endif
+
+	platform_set_mr(si, gd->bd->bi_memstart, gd->bd->bi_memsize, MR_ATTR_DRAM);
+	platform_set_mr(si, gd->bd->bi_flashstart, gd->bd->bi_flashsize, MR_ATTR_FLASH);
+	platform_set_mr(si, gd->bd->bi_sramstart, gd->bd->bi_sramsize, MR_ATTR_SRAM);
+
+	return 1;
+}
+
+#endif /* CONFIG_API */
diff --git a/api/api_private.h b/api/api_private.h
new file mode 100644
index 0000000..94a7fc5
--- /dev/null
+++ b/api/api_private.h
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _API_PRIVATE_H_
+#define _API_PRIVATE_H_
+
+void	api_init(void);
+void	platform_set_mr(struct sys_info *, unsigned long, unsigned long, int);
+int	platform_sys_info(struct sys_info *);
+
+void	dev_enum_reset(void);
+int	dev_enum_storage(struct device_info *);
+int	dev_enum_net(struct device_info *);
+
+int	dev_open_stor(void *);
+int	dev_open_net(void *);
+int	dev_close_stor(void *);
+int	dev_close_net(void *);
+
+lbasize_t	dev_read_stor(void *, void *, lbasize_t, lbastart_t);
+int		dev_read_net(void *, void *, int);
+int		dev_write_net(void *, void *, int);
+
+void dev_stor_init(void);
+
+#endif /* _API_PRIVATE_H_ */
diff --git a/api/api_storage.c b/api/api_storage.c
new file mode 100644
index 0000000..7cd4efb
--- /dev/null
+++ b/api/api_storage.c
@@ -0,0 +1,370 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_API)
+
+#include <common.h>
+#include <api_public.h>
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+#define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0)
+
+
+#define ENUM_IDE	0
+#define ENUM_USB	1
+#define ENUM_SCSI	2
+#define ENUM_MMC	3
+#define ENUM_MAX	4
+
+struct stor_spec {
+	int		max_dev;
+	int		enum_started;
+	int		enum_ended;
+	int		type;		/* "external" type: DT_STOR_{IDE,USB,etc} */
+	char		name[4];
+};
+
+static struct stor_spec specs[ENUM_MAX] = { { 0, 0, 0, 0, "" }, };
+
+
+void dev_stor_init(void)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_IDE)
+	specs[ENUM_IDE].max_dev = CFG_IDE_MAXDEVICE;
+	specs[ENUM_IDE].enum_started = 0;
+	specs[ENUM_IDE].enum_ended = 0;
+	specs[ENUM_IDE].type = DEV_TYP_STOR | DT_STOR_IDE;
+	specs[ENUM_IDE].name = "ide";
+#endif
+#if (CONFIG_COMMANDS & CFG_CMD_USB)
+	specs[ENUM_USB].max_dev = USB_MAX_STOR_DEV;
+	specs[ENUM_USB].enum_started = 0;
+	specs[ENUM_USB].enum_ended = 0;
+	specs[ENUM_USB].type = DEV_TYP_STOR | DT_STOR_USB;
+	specs[ENUM_USB].name = "usb";
+#endif
+#if (CONFIG_COMMANDS & CFG_CMD_SCSI)
+	specs[ENUM_SCSI].max_dev = CFG_SCSI_MAX_DEVICE;
+	specs[ENUM_SCSI].enum_started = 0;
+	specs[ENUM_SCSI].enum_ended = 0;
+	specs[ENUM_SCSI].type = DEV_TYP_STOR | DT_STOR_SCSI;
+	specs[ENUM_SCSI].name = "scsi";
+#endif
+}
+
+/*
+ * Finds next available device in the storage group
+ *
+ * type:	storage group type - ENUM_IDE, ENUM_SCSI etc.
+ *
+ * first:	if 1 the first device in the storage group is returned (if
+ *              exists), if 0 the next available device is searched
+ *
+ * more:	returns 0/1 depending if there are more devices in this group
+ *		available (for future iterations)
+ *
+ * returns:	0/1 depending if device found in this iteration
+ */
+static int dev_stor_get(int type, int first, int *more, struct device_info *di)
+{
+	int found = 0;
+	*more = 0;
+
+	int i;
+
+	block_dev_desc_t *dd;
+
+	if (first) {
+		di->cookie = (void *)get_dev(specs[type].name, 0);
+		found = 1;
+
+	} else {
+		for (i = 0; i < specs[type].max_dev; i++)
+			if (di->cookie == (void *)get_dev(specs[type].name, i)) {
+				/* previous cookie found -- advance to the
+				 * next device, if possible */
+
+				if (++i >= specs[type].max_dev) {
+					/* out of range, no more to enum */
+					di->cookie = NULL;
+					break;
+				}
+
+				di->cookie = (void *)get_dev(specs[type].name, i);
+				found = 1;
+
+				/* provide hint if there are more devices in
+				 * this group to enumerate */
+				if ((i + 1) < specs[type].max_dev)
+					*more = 1;
+
+				break;
+			}
+	}
+
+	if (found) {
+		di->type = specs[type].type;
+
+		if (di->cookie != NULL) {
+			dd = (block_dev_desc_t *)di->cookie;
+			if (dd->type == DEV_TYPE_UNKNOWN) {
+				debugf("device instance exists, but is not active..");
+				found = 0;
+			} else {
+				di->di_stor.block_count = dd->lba;
+				di->di_stor.block_size = dd->blksz;
+			}
+		}
+
+	} else
+		di->cookie = NULL;
+
+	return found;
+}
+
+
+/*
+ * returns:	ENUM_IDE, ENUM_USB etc. based on block_dev_desc_t
+ */
+static int dev_stor_type(block_dev_desc_t *dd)
+{
+	int i, j;
+
+	for (i = ENUM_IDE; i < ENUM_MAX; i++)
+		for (j = 0; j < specs[i].max_dev; j++)
+			if (dd == get_dev(specs[i].name, j))
+				return i;
+
+	return ENUM_MAX;
+}
+
+
+/*
+ * returns:	0/1 whether cookie points to some device in this group
+ */
+static int dev_is_stor(int type, struct device_info *di)
+{
+	return (dev_stor_type(di->cookie) == type) ? 1 : 0;
+}
+
+
+static int dev_enum_stor(int type, struct device_info *di)
+{
+	int found = 0, more = 0;
+
+	debugf("called, type %d\n", type);
+
+	/*
+	 * Formulae for enumerating storage devices:
+	 * 1. if cookie (hint from previous enum call) is NULL we start again
+	 *    with enumeration, so return the first available device, done.
+	 *
+	 * 2. if cookie is not NULL, check if it identifies some device in
+	 *    this group:
+	 *
+	 * 2a. if cookie is a storage device from our group (IDE, USB etc.),
+	 *     return next available (if exists) in this group
+	 *
+	 * 2b. if it isn't device from our group, check if such devices were
+	 *     ever enumerated before:
+	 *     - if not, return the first available device from this group
+	 *     - else return 0
+	 */
+
+	if (di->cookie == NULL) {
+
+		debugf("group%d - enum restart\n", type);
+
+		/*
+		 * 1. Enumeration (re-)started: take the first available
+		 * device, if exists
+		 */
+		found = dev_stor_get(type, 1, &more, di);
+		specs[type].enum_started = 1;
+
+	} else if (dev_is_stor(type, di)) {
+
+		debugf("group%d - enum continued for the next device\n", type);
+
+		if (specs[type].enum_ended) {
+			debugf("group%d - nothing more to enum!\n", type);
+			return 0;
+		}
+
+		/* 2a. Attempt to take a next available device in the group */
+		found = dev_stor_get(type, 0, &more, di);
+
+	} else {
+
+		if (specs[type].enum_ended) {
+			debugf("group %d - already enumerated, skipping\n", type);
+			return 0;
+		}
+
+		debugf("group%d - first time enum\n", type);
+
+		if (specs[type].enum_started == 0) {
+			/*
+			 * 2b.  If enumerating devices in this group did not
+			 * happen before, it means the cookie pointed to a
+			 * device frome some other group (another storage
+			 * group, or network); in this case try to take the
+			 * first available device from our group
+			 */
+			specs[type].enum_started = 1;
+
+			/*
+			 * Attempt to take the first device in this group:
+			 *'first element' flag is set
+			 */
+			found = dev_stor_get(type, 1, &more, di);
+
+		} else {
+			errf("group%d - out of order iteration\n", type);
+			found = 0;
+			more = 0;
+		}
+	}
+
+	/*
+	 * If there are no more devices in this group, consider its
+	 * enumeration finished
+	 */
+	specs[type].enum_ended = (!more) ? 1 : 0;
+
+	if (found)
+		debugf("device found, returning cookie 0x%08x\n",
+			(u_int32_t)di->cookie);
+	else
+		debugf("no device found\n");
+
+	return found;
+}
+
+void dev_enum_reset(void)
+{
+	int i;
+
+	for (i = 0; i < ENUM_MAX; i ++) {
+		specs[i].enum_started = 0;
+		specs[i].enum_ended = 0;
+	}
+}
+
+int dev_enum_storage(struct device_info *di)
+{
+	int i;
+
+	/*
+	 * check: ide, usb, scsi, mmc
+	 */
+	for (i = ENUM_IDE; i < ENUM_MAX; i ++) {
+		if (dev_enum_stor(i, di))
+			return 1;
+	}
+
+	return 0;
+}
+
+static int dev_stor_is_valid(int type, block_dev_desc_t *dd)
+{
+	int i;
+
+	for (i = 0; i < specs[type].max_dev; i++)
+		if (dd == get_dev(specs[type].name, i))
+			if (dd->type != DEV_TYPE_UNKNOWN)
+				return 1;
+
+	return 0;
+}
+
+
+int dev_open_stor(void *cookie)
+{
+	int type = dev_stor_type(cookie);
+
+	if (type == ENUM_MAX)
+		return API_ENODEV;
+
+	if (dev_stor_is_valid(type, (block_dev_desc_t *)cookie))
+		return 0;
+
+	return API_ENODEV;
+}
+
+
+int dev_close_stor(void *cookie)
+{
+	/*
+	 * Not much to do as we actually do not alter storage devices upon
+	 * close
+	 */
+	return 0;
+}
+
+
+static int dev_stor_index(block_dev_desc_t *dd)
+{
+	int i, type;
+
+	type = dev_stor_type(dd);
+	for (i = 0; i < specs[type].max_dev; i++)
+		if (dd == get_dev(specs[type].name, i))
+			return i;
+
+	return (specs[type].max_dev);
+}
+
+
+lbasize_t dev_read_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start)
+{
+	int type;
+	block_dev_desc_t *dd = (block_dev_desc_t *)cookie;
+
+	if ((type = dev_stor_type(dd)) == ENUM_MAX)
+		return 0;
+
+	if (!dev_stor_is_valid(type, dd))
+		return 0;
+
+	if ((dd->block_read) == NULL) {
+		debugf("no block_read() for device 0x%08x\n");
+		return 0;
+	}
+
+	return (dd->block_read(dev_stor_index(dd), start, len, buf));
+}
+
+#endif /* CONFIG_API */
diff --git a/api_examples/Makefile b/api_examples/Makefile
new file mode 100644
index 0000000..5812bcd
--- /dev/null
+++ b/api_examples/Makefile
@@ -0,0 +1,103 @@
+#
+# (C) Copyright 2007 Semihalf
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 Foundatio; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+ifeq ($(ARCH),ppc)
+LOAD_ADDR = 0x40000
+endif
+
+#ifeq ($(ARCH),arm)
+#LOAD_ADDR = 0xc100000
+#endif
+
+include $(TOPDIR)/config.mk
+
+ELF	+= demo
+BIN	+= demo.bin
+
+#CFLAGS += -v
+
+COBJS	:= $(ELF:=.o)
+SOBJS	:= crt0.o
+ifeq ($(ARCH),ppc)
+SOBJS	+= ppcstring.o
+endif
+
+LIB	= $(obj)libglue.a
+LIBCOBJS= glue.o crc32.o ctype.o string.o vsprintf.o libgenwrap.o
+
+LIBOBJS	= $(addprefix $(obj),$(SOBJS) $(LIBCOBJS))
+
+SRCS	:= $(COBJS:.o=.c) $(LIBCOBJS:.o=.c) $(SOBJS:.o=.S)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+ELF	:= $(addprefix $(obj),$(ELF))
+BIN	:= $(addprefix $(obj),$(BIN))
+
+gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`)
+
+CPPFLAGS += -I..
+
+all:	$(obj).depend $(OBJS) $(LIB) $(BIN) $(ELF)
+
+#########################################################################
+$(LIB):	$(obj).depend $(LIBOBJS)
+		$(AR) $(ARFLAGS) $@ $(LIBOBJS)
+
+$(ELF):
+$(obj)%:	$(obj)%.o $(LIB)
+		$(LD) $(obj)crt0.o -Ttext $(LOAD_ADDR) \
+			-o $@ $< $(LIB) \
+			-L$(gcclibdir) -lgcc
+
+$(BIN):
+$(obj)%.bin:	$(obj)%
+		$(OBJCOPY) -O binary $< $@ 2>/dev/null
+
+$(obj)crc32.c: 
+	@rm -f $(obj)crc32.c
+	ln -s $(src)../lib_generic/crc32.c $(obj)crc32.c
+
+$(obj)ctype.c:
+	@rm -f $(obj)ctype.c
+	ln -s $(src)../lib_generic/ctype.c $(obj)ctype.c
+
+$(obj)string.c:
+	@rm -f $(obj)string.c
+	ln -s $(src)../lib_generic/string.c $(obj)string.c
+
+$(obj)vsprintf.c:
+	@rm -f $(obj)vsprintf.c
+	ln -s $(src)../lib_generic/vsprintf.c $(obj)vsprintf.c
+
+ifeq ($(ARCH),ppc)
+$(obj)ppcstring.S:
+	@rm -f $(obj)ppcstring.S
+	ln -s $(src)../lib_ppc/ppcstring.S $(obj)ppcstring.S
+endif
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/api_examples/crt0.S b/api_examples/crt0.S
new file mode 100644
index 0000000..8d4f706
--- /dev/null
+++ b/api_examples/crt0.S
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#if defined(CONFIG_PPC)
+
+	.text
+
+	.globl _start
+_start:
+	b	main
+
+
+	.globl syscall
+syscall:
+	lis	%r11, syscall_ptr@ha
+	addi	%r11, %r11, syscall_ptr@l
+	lwz	%r11, 0(%r11)
+	mtctr	%r11
+	bctr
+
+
+	.globl syscall_ptr
+syscall_ptr:
+	.align	4
+	.long	0
+#else
+#error No support for this arch!
+#endif
diff --git a/api_examples/demo.c b/api_examples/demo.c
new file mode 100644
index 0000000..a4aeef1
--- /dev/null
+++ b/api_examples/demo.c
@@ -0,0 +1,258 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+#include "glue.h"
+
+#define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0)
+
+void	test_dump_si(struct sys_info *);
+void	test_dump_di(int);
+void	test_dump_sig(struct api_signature *);
+
+char buf[2048];
+
+#define WAIT_SECS 5
+
+int main(int argc, char *argv[])
+{
+	int rv = 0;
+	int h, i, j;
+	int devs_no;
+	struct api_signature *sig = NULL;
+	ulong start, now;
+	struct device_info *di;
+
+	if (!api_search_sig(&sig))
+		return -1;
+
+	syscall_ptr = sig->syscall;
+	if (syscall_ptr == NULL)
+		return -2;
+
+	if (sig->version > API_SIG_VERSION)
+		return -3;
+
+	printf("API signature found @%x\n", sig);
+	test_dump_sig(sig);
+
+	printf("\n*** Consumer API test ***\n");
+	printf("syscall ptr 0x%08x@%08x\n", syscall_ptr, &syscall_ptr);
+
+	/* console activities */
+	ub_putc('B');
+
+	printf("*** Press any key to continue ***\n");
+	printf("got char 0x%x\n", ub_getc());
+
+	/* system info */
+	test_dump_si(ub_get_sys_info());
+
+	/* timing */
+	printf("\n*** Timing - wait a couple of secs ***\n");
+	start = ub_get_timer(0);
+	printf("\ntime: start %lu\n\n", start);
+	for (i = 0; i < WAIT_SECS; i++)
+		for (j = 0; j < 1000; j++)
+			ub_udelay(1000);	/* wait 1 ms */
+
+	/* this is the number of milliseconds that passed from ub_get_timer(0) */
+	now = ub_get_timer(start);
+	printf("\ntime: now %lu\n\n", now);
+
+	/* enumerate devices */
+	printf("\n*** Enumerate devices ***\n");
+	devs_no = ub_dev_enum();
+	
+	printf("Number of devices found: %d\n", devs_no);
+	if (devs_no == 0)
+		return -1;
+
+
+	printf("\n*** Show devices ***\n");
+	for (i = 0; i < devs_no; i++) {
+		test_dump_di(i);
+		printf("\n");
+	}
+
+	printf("\n*** Operations on devices ***\n");
+
+	/* test opening a device already opened */
+	h = 0;
+	if ((rv = ub_dev_open(h)) != 0) {
+		errf("open device %d error %d\n", h, rv);
+		return -1;
+	}
+	if ((rv = ub_dev_open(h)) != 0)
+		errf("open device %d error %d\n", h, rv);
+
+	ub_dev_close(h);
+
+	/* test storage */
+	printf("Trying storage devices...\n");
+	for (i = 0; i < devs_no; i++) {
+		di = ub_dev_get(i);
+
+		if (di->type & DEV_TYP_STOR)
+			break;
+
+	}
+	if (i == devs_no)
+		printf("No storage devices available\n");
+	else {
+		if ((rv = ub_dev_open(i)) != 0)
+			errf("open device %d error %d\n", i, rv);
+		else if ((rv = ub_dev_read(i, &buf, 200, 20)) != 0)
+			errf("could not read from device %d, error %d\n", i, rv);
+
+		ub_dev_close(i);
+	}
+
+	/* test networking */
+	printf("Trying network devices...\n");
+	for (i = 0; i < devs_no; i++) {
+		di = ub_dev_get(i);
+
+		if (di->type == DEV_TYP_NET)
+			break;
+
+	}
+	if (i == devs_no)
+		printf("No network devices available\n");
+	else {
+		if ((rv = ub_dev_open(i)) != 0)
+			errf("open device %d error %d\n", i, rv);
+		else if ((rv = ub_dev_send(i, &buf, 2048)) != 0)
+			errf("could not send to device %d, error %d\n", i, rv);
+
+		ub_dev_close(i);
+	}
+
+	if (ub_dev_close(h) != 0)
+		errf("could not close device %d\n", h);
+
+	printf("\n*** Env vars ***\n");
+
+	printf("ethact = %s\n", ub_env_get("ethact"));
+	printf("old fileaddr = %s\n", ub_env_get("fileaddr"));
+	ub_env_set("fileaddr", "deadbeef");
+	printf("new fileaddr = %s\n", ub_env_get("fileaddr"));
+
+	const char *env = NULL;
+
+	while ((env = ub_env_enum(env)) != NULL)
+		printf("%s = %s\n", env, ub_env_get(env));
+
+	/* reset */
+	ub_reset();
+	printf("\nHmm, reset returned...?!\n");
+
+	return rv;
+}
+
+void test_dump_sig(struct api_signature *sig)
+{
+	printf("signature:\n");
+	printf("  version\t= %d\n", sig->version);
+	printf("  checksum\t= 0x%08x\n", sig->checksum);
+	printf("  sc entry\t= 0x%08x\n", sig->syscall);
+}
+
+void test_dump_si(struct sys_info *si)
+{
+	int i;
+
+	printf("sys info:\n");
+	printf("  clkbus\t= 0x%08x\n", si->clk_bus);
+	printf("  clkcpu\t= 0x%08x\n", si->clk_cpu);
+	printf("  bar\t\t= 0x%08x\n", si->bar);
+
+	printf("---\n");
+	for (i = 0; i < si->mr_no; i++) {
+		if (si->mr[i].flags == 0)
+			break;
+
+		printf("  start\t= 0x%08lx\n", si->mr[i].start);
+		printf("  size\t= 0x%08lx\n", si->mr[i].size);
+
+		switch(si->mr[i].flags & 0x000F) {
+			case MR_ATTR_FLASH:
+				printf("  type FLASH\n");
+				break;
+			case MR_ATTR_DRAM:
+				printf("  type DRAM\n");
+				break;
+			case MR_ATTR_SRAM:
+				printf("  type SRAM\n");
+				break;
+			default:
+				printf("  type UNKNOWN\n");
+		}
+		printf("---\n");
+	}
+}
+
+static char * test_stor_typ(int type)
+{
+	if (type & DT_STOR_IDE)
+		return "IDE";
+
+	if (type & DT_STOR_SCSI)
+		return "SCSI";
+
+	if (type & DT_STOR_USB)
+		return "USB";
+
+	if (type & DT_STOR_MMC);
+		return "MMC";
+
+	return "Unknown";
+}
+
+void test_dump_di(int handle)
+{
+	int i;
+	struct device_info *di = ub_dev_get(handle);
+
+	printf("device info (%d):\n", handle);
+	printf("  cookie\t= 0x%08x\n", (uint32_t)di->cookie);
+	printf("  type\t\t= 0x%08x\n", di->type);
+
+	if (di->type == DEV_TYP_NET) {
+		printf("  hwaddr\t= ");
+		for (i = 0; i < 6; i++)
+			printf("%02x ", di->di_net.hwaddr[i]);
+
+		printf("\n");
+
+	} else if (di->type & DEV_TYP_STOR) {
+		printf("  type\t\t= %s\n", test_stor_typ(di->type));
+		printf("  blk size\t\t= %d\n", di->di_stor.block_size);
+		printf("  blk count\t\t= %d\n", di->di_stor.block_count);
+	}
+}
diff --git a/api_examples/glue.c b/api_examples/glue.c
new file mode 100644
index 0000000..7598369
--- /dev/null
+++ b/api_examples/glue.c
@@ -0,0 +1,405 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+#include "glue.h"
+
+static int valid_sig(struct api_signature *sig)
+{
+	uint32_t checksum;
+	struct api_signature s;
+
+	if (sig == NULL)
+		return 0;
+	/*
+	 * Clear the checksum field (in the local copy) so as to calculate the
+	 * CRC with the same initial contents as at the time when the sig was
+	 * produced
+	 */
+	s = *sig;
+	s.checksum = 0;
+
+	checksum = crc32(0, (unsigned char *)&s, sizeof(struct api_signature));
+
+	if (checksum != sig->checksum)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Searches for the U-Boot API signature
+ *
+ * returns 1/0 depending on found/not found result
+ */
+int api_search_sig(struct api_signature **sig) {
+
+	unsigned char *sp;
+
+	if (sig == NULL)
+		return 0;
+
+	sp = (unsigned char *)API_SEARCH_START;
+
+	while ((sp + (int)API_SIG_MAGLEN) < (unsigned char *)API_SEARCH_END) {
+		if (!memcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) {
+			*sig = (struct api_signature *)sp;
+			if (valid_sig(*sig))
+				return 1;
+		}
+		sp += API_SIG_MAGLEN;
+	}
+
+	*sig = NULL;
+	return 0;
+}
+
+/****************************************
+ *
+ * console
+ *
+ ****************************************/
+
+int ub_getc(void)
+{
+	int c;
+
+	if (!syscall(API_GETC, NULL, (uint32_t)&c))
+		return -1;
+
+	return c;
+}
+
+int ub_tstc(void)
+{
+	int t;
+
+	if (!syscall(API_TSTC, NULL, (uint32_t)&t))
+		return -1;
+
+	return t;
+}
+
+void ub_putc(char c)
+{
+	syscall(API_PUTC, NULL, (uint32_t)&c);
+}
+
+void ub_puts(const char *s)
+{
+	syscall(API_PUTS, NULL, (uint32_t)s);
+}
+
+/****************************************
+ *
+ * system
+ *
+ ****************************************/
+
+void ub_reset(void)
+{
+	syscall(API_RESET, NULL);
+}
+
+#define MR_MAX 5
+static struct mem_region mr[MR_MAX];
+static struct sys_info si;
+
+struct sys_info * ub_get_sys_info(void)
+{
+	int err = 0;
+
+	memset(&si, 0, sizeof(struct sys_info));
+	si.mr = mr;
+	si.mr_no = MR_MAX;
+	memset(&mr, 0, sizeof(mr));
+
+	if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si))
+		return NULL;
+
+	return ((err) ? NULL : &si);
+}
+
+/****************************************
+ *
+ * timing
+ *
+ ****************************************/
+ 
+void ub_udelay(unsigned long usec)
+{
+	syscall(API_UDELAY, NULL, &usec);
+}
+
+unsigned long ub_get_timer(unsigned long base)
+{
+	unsigned long cur;
+
+	if (!syscall(API_GET_TIMER, NULL, &cur, &base))
+		return 0;
+
+	return cur;
+}
+
+
+/****************************************************************************
+ *
+ * devices
+ *
+ * Devices are identified by handles: numbers 0, 1, 2, ..., MAX_DEVS-1
+ *
+ ***************************************************************************/
+
+#define MAX_DEVS 6
+
+static struct device_info devices[MAX_DEVS];
+
+struct device_info * ub_dev_get(int i)
+{
+	return ((i < 0 || i >= MAX_DEVS) ? NULL : &devices[i]);
+}
+
+/*
+ * Enumerates the devices: fills out device_info elements in the devices[]
+ * array.
+ *
+ * returns:		number of devices found
+ */
+int ub_dev_enum(void)
+{
+	struct device_info *di;
+	int n = 0;
+
+	memset(&devices, 0, sizeof(struct device_info) * MAX_DEVS);
+	di = &devices[0];
+
+	if (!syscall(API_DEV_ENUM, NULL, di))
+		return 0;
+
+	while (di->cookie != NULL) {
+
+		if (++n >= MAX_DEVS)
+			break;
+
+		/* take another device_info */
+		di++;
+
+		/* pass on the previous cookie */
+		di->cookie = devices[n - 1].cookie;
+
+		if (!syscall(API_DEV_ENUM, NULL, di))
+			return 0;
+	}
+
+	return n;
+}
+
+/*
+ * handle:	0-based id of the device
+ *
+ * returns:	0 when OK, err otherwise
+ */
+int ub_dev_open(int handle)
+{
+	struct device_info *di;
+	int err = 0;
+
+	if (handle < 0 || handle >= MAX_DEVS)
+		return API_EINVAL;
+
+	di = &devices[handle];
+
+	if (!syscall(API_DEV_OPEN, &err, di))
+		return -1;
+
+	return err;
+}
+
+int ub_dev_close(int handle)
+{
+	struct device_info *di;
+
+	if (handle < 0 || handle >= MAX_DEVS)
+		return API_EINVAL;
+
+	di = &devices[handle];
+	if (!syscall(API_DEV_CLOSE, NULL, di))
+		return -1;
+
+	return 0;
+}
+
+/*
+ *
+ * Validates device for read/write, it has to:
+ *
+ * - have sane handle
+ * - be opened
+ *
+ * returns:	0/1 accordingly
+ */
+static int dev_valid(int handle)
+{
+	if (handle < 0 || handle >= MAX_DEVS)
+		return 0;
+
+	if (devices[handle].state != DEV_STA_OPEN)
+		return 0;
+
+	return 1;
+}
+
+static int dev_stor_valid(int handle)
+{
+	if (!dev_valid(handle))
+		return 0;
+
+	if (!(devices[handle].type & DEV_TYP_STOR))
+		return 0;
+
+	return 1;
+}
+
+int ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start)
+{
+	struct device_info *di;
+	lbasize_t act_len;
+	int err = 0;
+
+	if (!dev_stor_valid(handle))
+		return API_ENODEV;
+
+	di = &devices[handle];
+	if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len))
+		return -1;
+
+	if (err) 
+		return err;
+
+	if (act_len != len)
+		return API_EIO;
+
+	return 0;
+}
+
+static int dev_net_valid(int handle)
+{
+	if (!dev_valid(handle))
+		return 0;
+
+	if (devices[handle].type != DEV_TYP_NET)
+		return 0;
+
+	return 1;
+}
+
+int ub_dev_recv(int handle, void *buf, int len)
+{
+	struct device_info *di;
+	int err = 0, act_len;
+
+	if (!dev_net_valid(handle))
+		return API_ENODEV;
+
+	di = &devices[handle];
+	if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len))
+		return -1;
+
+	if (err)
+		return -1;
+
+	return act_len;
+}
+
+int ub_dev_send(int handle, void *buf, int len)
+{
+	struct device_info *di;
+	int err = 0;
+
+	if (!dev_net_valid(handle))
+		return API_ENODEV;
+
+	di = &devices[handle];
+	if (!syscall(API_DEV_WRITE, &err, di, buf, &len))
+		return -1;
+
+	return err;
+}
+
+/****************************************
+ *
+ * env vars
+ *
+ ****************************************/
+
+char * ub_env_get(const char *name)
+{
+	char *value;
+
+	if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value))
+		return NULL;
+
+	return value;
+}
+
+void ub_env_set(const char *name, char *value)
+{
+	syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value);
+}
+
+
+static char env_name[256];
+
+const char * ub_env_enum(const char *last)
+{
+	const char *env, *str;
+	int i;
+
+	env = NULL;
+
+	/*
+	 * It's OK to pass only the name piece as last (and not the whole
+	 * 'name=val' string), since the API_ENUM_ENV call uses envmatch()
+	 * internally, which handles such case
+	 */
+	if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env))
+		return NULL;
+
+	if (!env)
+		/* no more env. variables to enumerate */
+		return NULL;
+
+	/* next enumerated env var */
+	memset(env_name, 0, 256);
+	for (i = 0, str = env; *str != '=' && *str != '\0';)
+		env_name[i++] = *str++;
+
+	env_name[i] = '\0';
+
+	return env_name;
+}
diff --git a/api_examples/glue.h b/api_examples/glue.h
new file mode 100644
index 0000000..a82f783
--- /dev/null
+++ b/api_examples/glue.h
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/*
+ * This is the header file for conveniency wrapper routines (API glue)
+ */
+
+#ifndef _API_GLUE_H_
+#define _API_GLUE_H_
+
+#define API_SEARCH_START	(255 * 1024 * 1024)	/* start at 1MB below top RAM */
+#define API_SEARCH_END		(256 * 1024 * 1024 - 1)	/* ...and search to the end */
+
+int	syscall(int, int *, ...);
+void *	syscall_ptr;
+
+int	api_search_sig(struct api_signature **sig);
+
+/*
+ * ub_ library calls are part of the application, not U-Boot code!  They are
+ * front-end wrappers that are used by the consumer application: they prepare
+ * arguments for particular syscall and jump to the low level syscall()
+ */
+
+/* console */
+int	ub_getc(void);
+int	ub_tstc(void);
+void	ub_putc(char c);
+void	ub_puts(const char *s);
+
+/* system */
+void			ub_reset(void);
+struct sys_info *	ub_get_sys_info(void);
+
+/* time */
+void		ub_udelay(unsigned long);
+unsigned long	ub_get_timer(unsigned long);
+
+/* env vars */
+char *		ub_env_get(const char *name);
+void		ub_env_set(const char *name, char *value);
+const char *	ub_env_enum(const char *last);
+
+/* devices */
+int			ub_dev_enum(void);
+int			ub_dev_open(int handle);
+int			ub_dev_close(int handle);
+int			ub_dev_read(int handle, void *buf,
+				lbasize_t len, lbastart_t start);
+int			ub_dev_send(int handle, void *buf, int len);
+int			ub_dev_recv(int handle, void *buf, int len);
+struct device_info *	ub_dev_get(int);
+
+#endif /* _API_GLUE_H_ */
diff --git a/api_examples/libgenwrap.c b/api_examples/libgenwrap.c
new file mode 100644
index 0000000..df62633
--- /dev/null
+++ b/api_examples/libgenwrap.c
@@ -0,0 +1,90 @@
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * This is is a set of wrappers/stubs that allow to use certain routines from
+ * U-Boot's lib_generic in the standalone app. This way way we can re-use
+ * existing code e.g. operations on strings and similar.
+ *
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+#include "glue.h"
+
+/*
+ * printf() and vprintf() are stolen from u-boot/common/console.c
+ */
+void printf (const char *fmt, ...)
+{
+	va_list args;
+	uint i;
+	char printbuffer[256];
+
+	va_start (args, fmt);
+
+	/* For this to work, printbuffer must be larger than
+	 * anything we ever want to print.
+	 */
+	i = vsprintf (printbuffer, fmt, args);
+	va_end (args);
+
+	/* Print the string */
+	ub_puts (printbuffer);
+}
+
+void vprintf (const char *fmt, va_list args)
+{
+	uint i;
+	char printbuffer[256];
+
+	/* For this to work, printbuffer must be larger than
+	 * anything we ever want to print.
+	 */
+	i = vsprintf (printbuffer, fmt, args);
+
+	/* Print the string */
+	ub_puts (printbuffer);
+}
+
+void putc (const char c)
+{
+	ub_putc(c);
+}
+
+void udelay(unsigned long usec)
+{
+	ub_udelay(usec);
+}
+
+void do_reset (void)
+{
+	ub_reset();
+}
+
+void *malloc(size_t len)
+{
+	return NULL;
+}
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 6770408..dd263b6 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -81,8 +81,6 @@
 /************************************************************************
 ************************************************************************/
 
-static int envmatch (uchar *, int);
-
 /*
  * Table with supported baudrates (defined in config_xyz.h)
  */
@@ -576,8 +574,7 @@
  * If the names match, return the index for the value2, else NULL.
  */
 
-static int
-envmatch (uchar *s1, int i2)
+int envmatch (uchar *s1, int i2)
 {
 
 	while (*s1 == env_get_char(i2++))
diff --git a/include/api_public.h b/include/api_public.h
new file mode 100644
index 0000000..690975e
--- /dev/null
+++ b/include/api_public.h
@@ -0,0 +1,102 @@
+#ifndef _API_PUBLIC_H_
+#define _API_PUBLIC_H_
+
+#define API_EINVAL		1	/* invalid argument(s)	*/
+#define API_ENODEV		2	/* no device		*/
+#define API_ENOMEM		3	/* no memory		*/
+#define API_EBUSY		4	/* busy, occupied etc.	*/
+#define API_EIO			5	/* I/O error		*/
+
+typedef	int (*scp_t)(int, int *, ...);
+
+#define API_SIG_VERSION	1
+#define API_SIG_MAGIC	"UBootAPI"
+#define API_SIG_MAGLEN	8
+
+struct api_signature {
+	char		magic[API_SIG_MAGLEN];	/* magic string */
+	uint16_t	version;		/* API version */
+	uint32_t	checksum;		/* checksum of this sig struct */
+	scp_t		syscall;		/* entry point to the API */
+};
+
+enum {
+	API_RSVD = 0,
+	API_GETC,
+	API_PUTC,
+	API_TSTC,
+	API_PUTS,
+	API_RESET,
+	API_GET_SYS_INFO,
+	API_UDELAY,
+	API_GET_TIMER,
+	API_DEV_ENUM,
+	API_DEV_OPEN,
+	API_DEV_CLOSE,
+	API_DEV_READ,
+	API_DEV_WRITE,
+	API_ENV_ENUM,
+	API_ENV_GET,
+	API_ENV_SET,
+	API_MAXCALL
+};
+
+#define MR_ATTR_FLASH	0x0001
+#define MR_ATTR_DRAM	0x0002
+#define MR_ATTR_SRAM	0x0003
+
+struct mem_region {
+	unsigned long	start;
+	unsigned long	size;
+	int		flags;
+};
+
+struct sys_info {
+	unsigned long		clk_bus;
+	unsigned long		clk_cpu;
+	unsigned long		bar;
+	struct mem_region	*mr;
+	int			mr_no;	/* number of memory regions */
+};
+
+#undef CFG_64BIT_LBA
+#ifdef CFG_64BIT_LBA
+typedef	u_int64_t lbasize_t;
+#else
+typedef unsigned long lbasize_t;
+#endif
+typedef unsigned long lbastart_t;
+
+#define DEV_TYP_NONE	0x0000
+#define DEV_TYP_NET	0x0001
+
+#define DEV_TYP_STOR	0x0002
+#define DT_STOR_IDE	0x0010
+#define DT_STOR_SCSI	0x0020
+#define DT_STOR_USB	0x0040
+#define DT_STOR_MMC	0x0080
+
+#define DEV_STA_CLOSED	0x0000		/* invalid, closed */
+#define DEV_STA_OPEN	0x0001		/* open i.e. active */
+
+struct device_info {
+	int	type;
+	void	*cookie;
+
+	union {
+		struct {
+			lbasize_t	block_count;	/* no of blocks */
+			unsigned long	block_size;	/* size of one block */
+		} storage;
+
+		struct {
+			unsigned char	hwaddr[6];
+		} net;
+	} info;
+#define di_stor info.storage
+#define di_net info.net
+
+	int	state;
+};
+
+#endif /* _API_PUBLIC_H_ */
diff --git a/include/common.h b/include/common.h
index 3b5bd8c..9ef9344 100644
--- a/include/common.h
+++ b/include/common.h
@@ -229,6 +229,7 @@
 /* common/cmd_nvedit.c */
 int	env_init     (void);
 void	env_relocate (void);
+int	envmatch     (uchar *, int);
 char	*getenv	     (char *);
 int	getenv_r     (char *name, char *buf, unsigned len);
 int	saveenv	     (void);
@@ -280,6 +281,9 @@
 /* common/exports.c */
 void	jumptable_init(void);
 
+/* api/api.c */
+void	api_init (void);
+
 /* common/memsize.c */
 long	get_ram_size  (volatile long *, long);
 
diff --git a/lib_ppc/board.c b/lib_ppc/board.c
index 9aa67f9..0719745 100644
--- a/lib_ppc/board.c
+++ b/lib_ppc/board.c
@@ -928,6 +928,11 @@
 	/* Initialize the jump table for applications */
 	jumptable_init ();
 
+#if defined(CONFIG_API)
+	/* Initialize API */
+	api_init ();
+#endif
+
 	/* Initialize the console (after the relocation and devices init) */
 	console_init_r ();