summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/main
diff options
context:
space:
mode:
authorroot <root@lamia.panaceas.james.local>2015-12-19 13:13:57 +0000
committerroot <root@lamia.panaceas.james.local>2015-12-19 14:18:03 +0000
commit1a2238d1bddc823df06f67312d96ccf9de2893cc (patch)
treec58a3944d674a667f133ea5a730f5037e57d3d2e /cfe/cfe/main
downloadbootloader-1a2238d1bddc823df06f67312d96ccf9de2893cc.tar.gz
bootloader-1a2238d1bddc823df06f67312d96ccf9de2893cc.tar.bz2
bootloader-1a2238d1bddc823df06f67312d96ccf9de2893cc.zip
CFE from danitool [without hostTools dir]: https://mega.nz/#!mwZyFK7a!CPT3BKC8dEw29kubtdYxhB91G9vIIismTkgzQ3iUy3k
Diffstat (limited to 'cfe/cfe/main')
-rw-r--r--cfe/cfe/main/cfe.mk301
-rw-r--r--cfe/cfe/main/cfe_attach.c265
-rw-r--r--cfe/cfe/main/cfe_autoboot.c456
-rw-r--r--cfe/cfe/main/cfe_background.c174
-rw-r--r--cfe/cfe/main/cfe_boot.c248
-rwxr-xr-xcfe/cfe/main/cfe_console.c1190
-rwxr-xr-xcfe/cfe/main/cfe_devfuncs.c279
-rw-r--r--cfe/cfe/main/cfe_error.c134
-rw-r--r--cfe/cfe/main/cfe_fatfs.c1983
-rwxr-xr-xcfe/cfe/main/cfe_filesys.c343
-rw-r--r--cfe/cfe/main/cfe_httpfs.c396
-rwxr-xr-xcfe/cfe/main/cfe_iocb_dispatch.c647
-rw-r--r--cfe/cfe/main/cfe_ldr_elf.c396
-rw-r--r--cfe/cfe/main/cfe_ldr_raw.c360
-rw-r--r--cfe/cfe/main/cfe_ldr_srec.c557
-rw-r--r--cfe/cfe/main/cfe_link.mk26
-rw-r--r--cfe/cfe/main/cfe_loader.c135
-rw-r--r--cfe/cfe/main/cfe_main.c636
-rw-r--r--cfe/cfe/main/cfe_mem.c256
-rw-r--r--cfe/cfe/main/cfe_rawfs.c293
-rw-r--r--cfe/cfe/main/cfe_savedata.c123
-rw-r--r--cfe/cfe/main/cfe_timer.c286
-rwxr-xr-xcfe/cfe/main/cfe_version.mk12
-rw-r--r--cfe/cfe/main/cfe_xreq.c346
-rw-r--r--cfe/cfe/main/cfe_zlibfs.c453
-rw-r--r--cfe/cfe/main/env_subr.c474
-rw-r--r--cfe/cfe/main/nvram_subr.c300
-rw-r--r--cfe/cfe/main/nvram_subr.h54
28 files changed, 11123 insertions, 0 deletions
diff --git a/cfe/cfe/main/cfe.mk b/cfe/cfe/main/cfe.mk
new file mode 100644
index 0000000..05b16b6
--- /dev/null
+++ b/cfe/cfe/main/cfe.mk
@@ -0,0 +1,301 @@
+
+#
+# CFE's version number
+#
+
+include ${TOP}/main/cfe_version.mk
+
+#
+# Default values for certain parameters
+#
+
+CFG_MLONG64 ?= 0
+CFG_LITTLE ?= 0
+CFG_RELOC ?= 0
+CFG_UNCACHED ?= 0
+CFG_NEWRELOC ?= 0
+CFG_BOOTRAM ?= 0
+CFG_VGACONSOLE ?= 0
+CFG_PCI ?= 1
+CFG_LDT_REV_017 ?= 0
+CFG_ZLIB ?= 0
+CFG_BIENDIAN ?= 0
+CFG_DOWNLOAD ?= 0
+CFG_RAMAPP ?= 0
+CFG_USB ?= 0
+
+#
+# Paths to other parts of the firmware. Everything's relative to ${TOP}
+# so that you can actually do a build anywhere you want.
+#
+
+ARCH_TOP = ${TOP}/arch/${ARCH}
+ARCH_SRC = ${ARCH_TOP}/common/src
+ARCH_INC = ${ARCH_TOP}/common/include
+CPU_SRC = ${ARCH_TOP}/cpu/${CPU}/src
+CPU_INC = ${ARCH_TOP}/cpu/${CPU}/include
+
+#
+# It's actually optional to have a 'board'
+# directory. If you don't specify BOARD,
+# don't include the files.
+#
+
+ifneq ("$(strip ${BOARD})","")
+BOARD_SRC = ${ARCH_TOP}/board/${BOARD}/src
+BOARD_INC = ${ARCH_TOP}/board/${BOARD}/include
+endif
+
+#
+# Preprocessor defines for CFE's version number
+#
+
+VDEF = -DCFE_VER_MAJ=${CFE_VER_MAJ} -DCFE_VER_MIN=${CFE_VER_MIN} -DCFE_VER_ECO=${CFE_VER_ECO}
+
+#
+# Construct the list of paths that will eventually become the include
+# paths and VPATH
+#
+
+SRCDIRS = ${ARCH_SRC} ${CPU_SRC} ${BOARD_SRC} ${TOP}/main ${TOP}/vendor ${TOP}/include ${TOP}/net ${TOP}/dev ${TOP}/pci ${TOP}/ui ${TOP}/lib ${TOP}/common ${TOP}/verif
+
+CFE_INC = ${TOP}/include ${TOP}/pci ${TOP}/net
+
+ifeq ($(strip ${CFG_VGACONSOLE}),1)
+SRCDIRS += ${TOP}/x86emu ${TOP}/pccons
+CFE_INC += ${TOP}/x86emu ${TOP}/pccons
+endif
+
+ifeq ($(strip ${CFG_VAPI}),1)
+SRCDIRS += ${TOP}/verif
+CFE_INC += ${TOP}/verif
+endif
+
+ifeq ($(strip ${CFG_ZLIB}),1)
+SRCDIRS += ${TOP}/zlib
+CFE_INC += ${TOP}/zlib
+endif
+
+
+INCDIRS = $(patsubst %,-I%,$(subst :, ,$(ARCH_INC) $(CPU_INC) $(BOARD_INC) $(CFE_INC)))
+
+VPATH = $(SRCDIRS)
+
+#
+# Bi-endian support: If we're building the little-endian
+# version, use a different linker script so we can locate the
+# ROM at a higher address. You'd think we could do this with
+# normal linker command line switches, but there appears to be no
+# command-line way to override the 'AT' qualifier in the linker script.
+#
+
+CFG_TEXTAT1MB=0
+ifeq ($(strip ${CFG_BIENDIAN}),1)
+ ifeq ($(strip ${CFG_LITTLE}),1)
+ CFG_TEXTAT1MB=1
+ endif
+endif
+
+
+#
+# Configure tools and basic tools flags. This include sets up
+# macros for calling the C compiler, basic flags,
+# and linker scripts.
+#
+
+include ${ARCH_SRC}/tools.mk
+
+#
+# Add some common flags that are used on any architecture.
+#
+
+CFLAGS += -I. $(INCDIRS)
+CFLAGS += -D_CFE_ ${VDEF} -DCFG_BOARDNAME=\"${CFG_BOARDNAME}\"
+
+#
+# Gross - allow more options to be supplied from command line
+#
+
+ifdef CFG_OPTIONS
+OPTFLAGS = $(patsubst %,-D%,$(subst :, ,$(CFG_OPTIONS)))
+CFLAGS += ${OPTFLAGS}
+endif
+
+
+#
+# This is the makefile's main target. Note that we actually
+# do most of the work in 'ALL' not 'all', since we include
+# other makefiles after this point.
+#
+
+all : build_date.c makereg pcidevs_data2.h ALL
+
+#
+# Macros that expand to the list of arch-independent files
+#
+
+DEVOBJS = dev_flash.o dev_newflash.o dev_null.o dev_promice.o \
+ dev_ide_common.o dev_ns16550.o dev_ds17887clock.o
+LIBOBJS = lib_malloc.o lib_printf.o lib_queue.o lib_string.o lib_string2.o \
+ lib_arena.o lib_misc.o lib_setjmp.o lib_qsort.o lib_hssubr.o lib_physio.o
+NETOBJS = net_ether.o net_arp.o net_ip.o net_udp.o net_api.o net_dns.o \
+ net_dhcp.o net_tftp.o net_icmp.o net_tcp.o net_tcpbuf.o dev_tcpconsole.o
+CFEOBJS = env_subr.o cfe_attach.o cfe_iocb_dispatch.o cfe_devfuncs.o \
+ nvram_subr.o cfe_console.o cfe_main.o cfe_mem.o cfe_timer.o \
+ cfe_background.o cfe_error.o build_date.o \
+ cfe_rawfs.o cfe_zlibfs.o cfe_xreq.o cfe_fatfs.o cfe_httpfs.o cfe_filesys.o cfe_boot.o \
+ cfe_autoboot.o cfe_ldr_elf.o cfe_ldr_raw.o cfe_ldr_srec.o cfe_loader.o url.o \
+ cfe_savedata.o
+UIOBJS = ui_command.o ui_cmddisp.o ui_envcmds.o ui_devcmds.o \
+ ui_netcmds.o ui_tcpcmds.o ui_memcmds.o ui_loadcmds.o ui_pcicmds.o \
+ ui_examcmds.o ui_flash.o ui_misccmds.o \
+ ui_test_disk.o ui_test_ether.o ui_test_flash.o ui_test_uart.o
+
+#
+# Add more object files if we're supporting PCI
+#
+
+ifeq ($(strip ${CFG_PCI}),1)
+PCIOBJS = pciconf.o ldtinit.o pci_subr.o
+PCIOBJS += pci_devs.o
+DEVOBJS += dev_sp1011.o dev_ht7520.o
+DEVOBJS += dev_ide_pci.o dev_ns16550_pci.o
+DEVOBJS += dev_tulip.o dev_dp83815.o
+CFLAGS += -DCFG_PCI=1
+ifeq ($(strip ${CFG_LDT_REV_017}),1)
+CFLAGS += -DCFG_LDT_REV_017=1
+endif
+ifeq ($(strip ${CFG_DOWNLOAD}),1)
+DEVOBJS += dev_bcm1250.o download.data
+CFLAGS += -DCFG_DOWNLOAD=1
+endif
+endif
+
+#
+# If doing bi-endian, add the compiler switch to change
+# the way the vectors are generated. These switches are
+# only added to the big-endian portion of the ROM,
+# which is located at the real boot vector.
+#
+
+ifeq ($(strip ${CFG_BIENDIAN}),1)
+ ifeq ($(strip ${CFG_LITTLE}),0)
+ CFLAGS += -DCFG_BIENDIAN=1
+ endif
+endif
+
+#
+# Include the makefiles for the architecture-common, cpu-specific,
+# and board-specific directories. Each of these will supply
+# some files to "ALLOBJS". The BOARD directory is optional
+# as some ports are so simple they don't need boad-specific stuff.
+#
+
+include ${ARCH_SRC}/Makefile
+include ${CPU_SRC}/Makefile
+
+ifneq ("$(strip ${BOARD})","")
+include ${BOARD_SRC}/Makefile
+endif
+
+#
+# Add the common object files here.
+#
+
+ALLOBJS += $(LIBOBJS) $(DEVOBJS) $(CFEOBJS) $(VENOBJS) $(UIOBJS) $(NETOBJS) $(PCIOBJS)
+
+#
+# VAPI continues to be a special case.
+#
+
+ifeq ($(strip ${CFG_VAPI}),1)
+include ${TOP}/verif/Makefile
+endif
+
+#
+# USB support
+#
+
+ifeq ($(strip ${CFG_USB}),1)
+SRCDIRS += ${TOP}/usb
+CFE_INC += ${TOP}/usb
+include ${TOP}/usb/Makefile
+endif
+
+#
+# If we're doing the VGA console thing, pull in the x86 emulator
+# and the pcconsole subsystem
+#
+
+ifeq ($(strip ${CFG_VGACONSOLE}),1)
+include ${TOP}/x86emu/Makefile
+include ${TOP}/pccons/Makefile
+endif
+
+#
+# If we're including ZLIB, then add its makefile.
+#
+
+ifeq ($(strip ${CFG_ZLIB}),1)
+include ${TOP}/zlib/Makefile
+CFLAGS += -DCFG_ZLIB=1 -DMY_ZCALLOC -DNO_MEMCPY
+endif
+
+#
+# Vendor extensions come next - they live in their own directory.
+#
+
+include ${TOP}/vendor/Makefile
+
+.PHONY : all
+.PHONY : ALL
+.PHONY : build_date.c
+
+#
+# Build the local tools that we use to construct other source files
+#
+
+mkpcidb : ${TOP}/hosttools/mkpcidb.c
+ gcc -o mkpcidb ${TOP}/hosttools/mkpcidb.c
+
+memconfig : ${TOP}/hosttools/memconfig.c
+ gcc -o memconfig -D_MCSTANDALONE_ -D_MCSTANDALONE_NOISY_ -I${TOP}/arch/mips/cpu/sb1250/include ${TOP}/hosttools/memconfig.c ${TOP}/arch/${ARCH}/cpu/${CPU}/src/sb1250_draminit.c
+
+pcidevs_data2.h : mkpcidb ${TOP}/pci/pcidevs_data.h
+ ./mkpcidb > pcidevs_data2.h
+
+mkflashimage : ${TOP}/hosttools/mkflashimage.c
+ gcc -o mkflashimage -I${TOP}/include ${TOP}/hosttools/mkflashimage.c
+
+pci_subr.o : ${TOP}/pci/pci_subr.c pcidevs_data2.h
+
+build_date.c :
+ echo "const char *builddate = \"`date`\";" > build_date.c
+ echo "const char *builduser = \"`whoami`@`hostname`\";" >> build_date.c
+
+#
+# Make a define for the board name
+#
+
+CFLAGS += -D_$(patsubst "%",%,${CFG_BOARDNAME})_
+
+LIBCFE = libcfe.a
+
+%.o : %.c
+ $(GCC) $(CFLAGS) -o $@ $<
+
+%.o : %.S
+ $(GCC) $(CFLAGS) -o $@ $<
+
+#
+# This rule constructs "libcfe.a" which contains most of the object
+# files.
+#
+
+$(LIBCFE) : $(ALLOBJS)
+ rm -f $(LIBCFE)
+ $(AR) cr $(LIBCFE) $(ALLOBJS)
+ $(RANLIB) $(LIBCFE)
+
+
+
diff --git a/cfe/cfe/main/cfe_attach.c b/cfe/cfe/main/cfe_attach.c
new file mode 100644
index 0000000..1235d6e
--- /dev/null
+++ b/cfe/cfe/main/cfe_attach.c
@@ -0,0 +1,265 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device Attach routines File: cfe_attach.c
+ *
+ * This module manages the list of device drivers. When a driver
+ * is probed, it can call cfe_attach to create actual device
+ * instances. The routines in this module manage the
+ * device list and the assignment of device names.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define CFE_MAX_DEVINST 64 /* max # of instances of devices */
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+/*
+ * Our device list.
+ */
+
+queue_t cfe_devices = {&cfe_devices, &cfe_devices};
+
+/* *********************************************************************
+ * cfe_finddev(name)
+ *
+ * Locate a device in the device list by its name and return
+ * a pointer to the device structure.
+ *
+ * Input parameters:
+ * name - name of device, e.g., "uart0"
+ *
+ * Return value:
+ * cfe_device_t pointer or NULL
+ ********************************************************************* */
+
+cfe_device_t *cfe_finddev(char *name)
+{
+ queue_t *qb;
+ cfe_device_t *dev;
+
+ for (qb = cfe_devices.q_next; qb != &cfe_devices; qb = qb->q_next) {
+ dev = (cfe_device_t *) qb;
+ if (strcmp(dev->dev_fullname,name) == 0) {
+ return dev;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * cfe_device_reset()
+ *
+ * Call all the "reset" methods in the devices on the device
+ * list. Note that the methods get called even when the
+ * devices are closed!
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_device_reset(void)
+{
+ queue_t *qb;
+ cfe_device_t *dev;
+
+ for (qb = cfe_devices.q_next; qb != &cfe_devices; qb = qb->q_next) {
+ dev = (cfe_device_t *) qb;
+ if (dev->dev_dispatch->dev_reset) {
+ (*(dev->dev_dispatch->dev_reset))(dev->dev_softc);
+ }
+ }
+}
+
+/* *********************************************************************
+ * cfe_attach_idx(drv,idx,softc,bootinfo,description)
+ *
+ * Add a device to the device list at a specific index. This
+ * is mainly used for devices like SCSI disks or CD-ROMs so
+ * we can use an index that matches the target ID or LUN.
+ *
+ * Input parameters:
+ * drv - driver structure (from the device driver module)
+ * idx - requested index (e.g., uartn where 'n' is the idx)
+ * softc - Unique information maintained for this device
+ * bootinfo - suffix for long form of the device name. For
+ * example, scsi0.3.1 might mean SCSI controller
+ * 0, device ID 3, LUN 1. The bootinfo would be
+ * "3.1"
+ * description - something nice to say for the devices command
+ *
+ * Return value:
+ * 0 if device has already been added at this index
+ * <0 for other problems
+ * 1 if we were successful.
+ ********************************************************************* */
+
+int cfe_attach_idx(cfe_driver_t *drv,int idx,void *softc,
+ char *bootinfo,char *description)
+{
+ char name[64];
+ cfe_device_t *dev;
+
+ xsprintf(name,"%s%d",drv->drv_bootname,idx);
+
+ if (bootinfo) {
+ strcat(name,".");
+ strcat(name,bootinfo);
+ }
+
+ if (cfe_finddev(name) != NULL) {
+ return 0;
+ }
+
+ dev = (cfe_device_t *) KMALLOC(sizeof(cfe_device_t),0);
+ if (!dev) return -1;
+
+ dev->dev_fullname = strdup(name);
+ dev->dev_softc = softc;
+ dev->dev_class = drv->drv_class;
+ dev->dev_dispatch = drv->drv_dispatch;
+ dev->dev_description = description ? strdup(description) : NULL;
+ dev->dev_opencount = 0;
+
+ q_enqueue(&cfe_devices,(queue_t *) dev);
+
+ return 1;
+
+}
+
+
+
+/* *********************************************************************
+ * cfe_attach(drv,softc,bootinfo,description
+ *
+ * Add a device to the system. This is a callback from the
+ * probe routine, and is used to actually add devices to CFE's
+ * device list.
+ *
+ * Input parameters:
+ * drv - driver structure (from the device driver module)
+ * softc - Unique information maintained for this device
+ * bootinfo - suffix for long form of the device name. For
+ * example, scsi0.3.1 might mean SCSI controller
+ * 0, device ID 3, LUN 1. The bootinfo would be
+ * "3.1"
+ * description - something nice to say for the devices command
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_attach(cfe_driver_t *drv,void *softc,
+ char *bootinfo,
+ char *description)
+{
+ int idx;
+ int res;
+
+ /*
+ * Try device indicies 0..CFE_MAX_DEVINST to assign a unique
+ * device name for this device. This is a really braindead way to
+ * do this, but how many devices are we expecting anyway?
+ */
+
+ for (idx = 0; idx < CFE_MAX_DEVINST; idx++) {
+
+ res = cfe_attach_idx(drv,idx,softc,bootinfo,description);
+
+ if (res < 0) break; /* out of memory or other badness */
+ if (res > 0) break; /* success! */
+ /* otherwise, try again, slot is taken */
+ }
+
+}
+
+/* *********************************************************************
+ * cfe_attach_init()
+ *
+ * Initialize this module.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void cfe_attach_init(void)
+{
+ q_init(&(cfe_devices));
+}
+
+
+/* *********************************************************************
+ * cfe_device_name(ctx)
+ *
+ * Given a device context, return a device name
+ *
+ * Input parameters:
+ * ctx - context
+ *
+ * Return value:
+ * name
+ ********************************************************************* */
+
+char *cfe_device_name(cfe_devctx_t *ctx)
+{
+ return ctx->dev_dev->dev_fullname;
+}
diff --git a/cfe/cfe/main/cfe_autoboot.c b/cfe/cfe/main/cfe_autoboot.c
new file mode 100644
index 0000000..14f3d3c
--- /dev/null
+++ b/cfe/cfe/main/cfe_autoboot.c
@@ -0,0 +1,456 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Automatic OS bootstrap File: cfe_autoboot.c
+ *
+ * This module handles OS bootstrap stuff. We use this version
+ * to do "automatic" booting; walking down a list of possible boot
+ * options, trying them until something good happens.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+
+#include "env_subr.h"
+#include "cfe.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_api.h"
+#include "cfe_fileops.h"
+#include "cfe_bootblock.h"
+#include "bsp_config.h"
+#include "cfe_boot.h"
+
+#include "cfe_loader.h"
+
+#include "cfe_autoboot.h"
+
+/* *********************************************************************
+ * data
+ ********************************************************************* */
+
+queue_t cfe_autoboot_list = {&cfe_autoboot_list,&cfe_autoboot_list};
+
+extern cfe_loadargs_t cfe_loadargs; /* from cfe_boot.c */
+extern const char *bootvar_device;
+extern const char *bootvar_file;
+extern const char *bootvar_flags;
+
+extern char *varchars;
+
+/* *********************************************************************
+ * macroexpand(instr,outstr)
+ *
+ * Expand environment variables in "instr" to "outstr"
+ *
+ * Input parameters:
+ * instr - to be expanded
+ * outstr - expanded.
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void macroexpand(char *instr,char *outstr)
+{
+ char macroname[50];
+ char *m;
+
+ while (*instr) {
+ if (*instr == '$') {
+ instr++;
+ m = macroname;
+ while (*instr && strchr(varchars,*instr)) {
+ *m++ = *instr++;
+ }
+ *m = '\0';
+ m = env_getenv(macroname);
+ if (m) {
+ while (*m) *outstr++ = *m++;
+ }
+ }
+ else {
+ *outstr++ = *instr++;
+ }
+ }
+
+ *outstr = '\0';
+}
+
+/* *********************************************************************
+ * cfe_tryauto_common(method,loadargs)
+ *
+ * Common portion of autoboot
+ *
+ * Input parameters:
+ * method - details on device to boot from
+ * filename - canonical name of file to load
+ * loadargs - cfe_loadargs_t of digested load parameters.
+ *
+ * Return value:
+ * does not return if successful
+ ********************************************************************* */
+
+static int cfe_tryauto_common(cfe_autoboot_method_t *method,
+ char *filename,
+ cfe_loadargs_t *la)
+{
+ int res;
+
+ la->la_filename = filename;
+ la->la_options = env_getenv(bootvar_flags);
+ la->la_filesys = method->ab_filesys;
+ la->la_device = method->ab_dev;
+ la->la_flags = method->ab_flags | LOADFLG_NOISY | LOADFLG_EXECUTE;
+ la->la_address = 0;
+ la->la_maxsize = 0;
+ la->la_entrypt = 0;
+
+ /* okay, go for it. */
+
+ xprintf("Loader:%s Filesys:%s Dev:%s File:%s Options:%s\n",
+ method->ab_loader,la->la_filesys,la->la_device,la->la_filename,la->la_options);
+
+ res = cfe_boot(method->ab_loader,&cfe_loadargs);
+
+ return res;
+
+}
+
+
+/* *********************************************************************
+ * cfe_tryauto_network(method)
+ *
+ * Try to autoboot from a network device.
+ *
+ * Input parameters:
+ * method - details on device to boot from
+ *
+ * Return value:
+ * does not return unless there is an error
+ ********************************************************************* */
+
+#if CFG_NETWORK
+static int cfe_tryauto_network(cfe_autoboot_method_t *method)
+{
+ int res;
+ dhcpreply_t *reply = NULL;
+ cfe_loadargs_t *la = &cfe_loadargs;
+ char buffer[512];
+ char *x;
+
+ /*
+ * First turn off any network interface that is currently active.
+ */
+
+ net_uninit();
+
+ /*
+ * Now activate the network hardware.
+ */
+
+ res = net_init(method->ab_dev);
+ if (res < 0) {
+ printf("Could not initialize network device %s: %s\n",
+ method->ab_dev,
+ cfe_errortext(res));
+ return res;
+ }
+
+ /*
+ * Do a DHCP query.
+ */
+
+ res = dhcp_bootrequest(&reply);
+ if (res < 0) {
+ printf("DHCP request failed on device %s: %s\n",method->ab_dev,
+ cfe_errortext(res));
+ net_uninit();
+ return res;
+ }
+
+ net_setparam(NET_IPADDR,reply->dr_ipaddr);
+ net_setparam(NET_NETMASK,reply->dr_netmask);
+ net_setparam(NET_GATEWAY,reply->dr_gateway);
+ net_setparam(NET_NAMESERVER,reply->dr_nameserver);
+ net_setparam(NET_DOMAIN,reply->dr_domainname);
+
+ /* Set all our environment variables. */
+ net_setnetvars();
+ dhcp_set_envvars(reply);
+
+ if (reply) dhcp_free_reply(reply);
+
+ /*
+ * Interface is now configured and ready, we can
+ * load programs now.
+ */
+
+ /*
+ * Construct the file name to load. If the method does not
+ * specify a file name directly, get it from DHCP.
+ *
+ * For network booting, the format of the file name
+ * is 'hostname:filename'
+ *
+ * If the method's filename includes a hostname, ignore
+ * BOOT_SERVER. Otherwise, combine BOOT_SERVER with the
+ * filename. This way we can provide the name here
+ * but have the file come off the server specified in the
+ * DHCP message.
+ */
+
+ if (method->ab_file && strchr(method->ab_file,':')) {
+ macroexpand(method->ab_file,buffer);
+ }
+ else {
+ buffer[0] = '\0';
+ x = env_getenv("BOOT_SERVER");
+ if (x) {
+ strcat(buffer,x);
+ strcat(buffer,":");
+ }
+
+ x = method->ab_file;
+ if (!x) x = env_getenv(bootvar_file);
+ if (x) {
+ strcat(buffer,x);
+ }
+ }
+
+ /* Okay, do it. */
+
+ cfe_tryauto_common(method,buffer,la);
+
+ /* If we get here, something bad happened. */
+
+ net_uninit();
+
+ return res;
+
+}
+
+#endif
+
+
+/* *********************************************************************
+ * cfe_tryauto_disk(method)
+ *
+ * Try to autoboot from a disk device.
+ *
+ * Input parameters:
+ * method - details on device to boot from
+ *
+ * Return value:
+ * does not return unless there is an error
+ ********************************************************************* */
+static int cfe_tryauto_disk(cfe_autoboot_method_t *method)
+{
+ int res;
+ cfe_loadargs_t *la = &cfe_loadargs;
+ char buffer[512];
+ char *filename;
+
+ buffer[0] = '\0';
+
+ if (method->ab_file) {
+ macroexpand(method->ab_file,buffer);
+ filename = buffer;
+ }
+ else {
+ filename = env_getenv("BOOT_FILE");
+ if (filename) strcpy(buffer,filename);
+ }
+
+ res = cfe_tryauto_common(method,filename,la);
+
+ return res;
+}
+
+/* *********************************************************************
+ * cfe_tryauto(method)
+ *
+ * Try a single autoboot method.
+ *
+ * Input parameters:
+ * method - autoboot method to try
+ *
+ * Return value:
+ * does not return if bootstrap is successful
+ * else error code
+ ********************************************************************* */
+
+static int cfe_tryauto(cfe_autoboot_method_t *method)
+{
+ switch (method->ab_type) {
+#if CFG_NETWORK
+ case CFE_AUTOBOOT_NETWORK:
+ return cfe_tryauto_network(method);
+ break;
+#endif
+
+ case CFE_AUTOBOOT_DISK:
+ case CFE_AUTOBOOT_RAW:
+ return cfe_tryauto_disk(method);
+ break;
+ }
+
+ return -1;
+}
+
+/* *********************************************************************
+ * cfe_autoboot(dev,flags)
+ *
+ * Try to perform an automatic system bootstrap
+ *
+ * Input parameters:
+ * dev - if not NULL, restrict bootstrap to named device
+ * flags - controls behaviour of cfe_autoboot
+ *
+ * Return value:
+ * should not return if bootstrap is successful, otherwise
+ * error code
+ ********************************************************************* */
+int cfe_autoboot(char *dev,int flags)
+{
+ queue_t *qb;
+ cfe_autoboot_method_t *method;
+ int res;
+ cfe_timer_t timer;
+ int forever;
+ int pollconsole;
+
+ forever = (flags & CFE_AUTOFLG_TRYFOREVER) ? 1 : 0;
+ pollconsole = (flags & CFE_AUTOFLG_POLLCONSOLE) ? 1 : 0;
+
+ do { /* potentially forever */
+ for (qb = cfe_autoboot_list.q_next; qb != &cfe_autoboot_list; qb = qb->q_next) {
+
+ method = (cfe_autoboot_method_t *) qb;
+
+ /*
+ * Skip other devices if we passed in a specific one.
+ */
+
+ if (dev && (strcmp(dev,method->ab_dev) != 0)) continue;
+
+ printf("\n*** Autoboot: Trying device '%s' ", method->ab_dev);
+ if (method->ab_file) printf("file %s ",method->ab_file);
+ printf("(%s,%s)\n\n",method->ab_dev,method->ab_filesys,method->ab_loader);
+
+ /*
+ * Scan keyboard if requested.
+ */
+ if (pollconsole) {
+ TIMER_SET(timer,CFE_HZ);
+ while (!TIMER_EXPIRED(timer)) {
+ POLL();
+ if (console_status()) goto done;
+ }
+ }
+
+ /*
+ * Try something. may not return.
+ */
+
+ res = cfe_tryauto(method);
+ }
+ } while (forever);
+
+ /* bail. */
+done:
+
+ printf("\n*** Autoboot failed.\n\n");
+
+ return -1;
+}
+
+
+/* *********************************************************************
+ * cfe_add_autoboot(type,flags,dev,loader,filesys,file)
+ *
+ * Add an autoboot method to the table.
+ * This is typically called in the board_finalinit one or more
+ * times to provide a list of bootstrap methods to try for autoboot
+ *
+ * Input parameters:
+ * type - CFE_AUTOBOOT_xxx (disk,network,raw)
+ * flags - loader flags (LOADFLG_xxx)
+ * loader - loader string (elf, raw, srec)
+ * filesys - file system string (raw, tftp, fat)
+ * file - name of file to load (if null, will try to guess)
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int cfe_add_autoboot(int type,int flags,char *dev,char *loader,char *filesys,char *file)
+{
+ cfe_autoboot_method_t *method;
+
+ method = (cfe_autoboot_method_t *) KMALLOC(sizeof(cfe_autoboot_method_t),0);
+
+ if (!method) return CFE_ERR_NOMEM;
+
+ method->ab_type = type;
+ method->ab_flags = flags;
+ method->ab_dev = dev;
+ method->ab_loader = loader;
+ method->ab_filesys = filesys;
+ method->ab_file = file;
+
+ q_enqueue(&cfe_autoboot_list,(queue_t *)method);
+ return 0;
+}
diff --git a/cfe/cfe/main/cfe_background.c b/cfe/cfe/main/cfe_background.c
new file mode 100644
index 0000000..9a64e0a
--- /dev/null
+++ b/cfe/cfe/main/cfe_background.c
@@ -0,0 +1,174 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Timer routines File: cfe_timer.c
+ *
+ * This module manages the list of routines to call periodically
+ * during "background processing." CFE has no interrupts or
+ * multitasking, so this is just where all the polling routines
+ * get called from.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define MAX_BACKGROUND_TASKS 16
+
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+static void (*cfe_bg_tasklist[MAX_BACKGROUND_TASKS])(void *);
+static void *cfe_bg_args[MAX_BACKGROUND_TASKS];
+
+
+/* *********************************************************************
+ * cfe_bg_init()
+ *
+ * Initialize the background task list
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_bg_init(void)
+{
+ memset(cfe_bg_tasklist,0,sizeof(cfe_bg_tasklist));
+}
+
+
+/* *********************************************************************
+ * cfe_bg_add(func,arg)
+ *
+ * Add a function to be called periodically in the background
+ * polling loop.
+ *
+ * Input parameters:
+ * func - function pointer
+ * arg - arg to pass to function
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_bg_add(void (*func)(void *x),void *arg)
+{
+ int idx;
+
+ for (idx = 0; idx < MAX_BACKGROUND_TASKS; idx++) {
+ if (cfe_bg_tasklist[idx] == NULL) {
+ cfe_bg_tasklist[idx] = func;
+ cfe_bg_args[idx] = arg;
+ return;
+ }
+ }
+}
+
+/* *********************************************************************
+ * cfe_bg_remove(func)
+ *
+ * Remove a function from the background polling loop
+ *
+ * Input parameters:
+ * func - function pointer
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_bg_remove(void (*func)(void *))
+{
+ int idx;
+
+ for (idx = 0; idx < MAX_BACKGROUND_TASKS; idx++) {
+ if (cfe_bg_tasklist[idx] == func) break;
+ }
+
+ if (idx == MAX_BACKGROUND_TASKS) return;
+
+ for (; idx < MAX_BACKGROUND_TASKS-1; idx++) {
+ cfe_bg_tasklist[idx] = cfe_bg_tasklist[idx+1];
+ cfe_bg_args[idx] = cfe_bg_args[idx+1];
+ }
+
+ cfe_bg_tasklist[idx] = NULL;
+ cfe_bg_args[idx] = NULL;
+}
+
+
+/* *********************************************************************
+ * background()
+ *
+ * The main loop and other places that wait for stuff call
+ * this routine to make sure the background handlers get their
+ * time.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void background(void)
+{
+ int idx;
+ void (*func)(void *arg);
+
+ for (idx = 0; idx < MAX_BACKGROUND_TASKS; idx++) {
+ func = cfe_bg_tasklist[idx];
+ if (func == NULL) break;
+ (*func)(cfe_bg_args[idx]);
+ }
+}
diff --git a/cfe/cfe/main/cfe_boot.c b/cfe/cfe/main/cfe_boot.c
new file mode 100644
index 0000000..12fecaa
--- /dev/null
+++ b/cfe/cfe/main/cfe_boot.c
@@ -0,0 +1,248 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * OS bootstrap File: cfe_boot.c
+ *
+ * This module handles OS bootstrap stuff
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+
+#include "env_subr.h"
+#include "cfe.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_api.h"
+#include "cfe_fileops.h"
+#include "cfe_bootblock.h"
+#include "bsp_config.h"
+#include "cfe_boot.h"
+
+#include "cfe_loader.h"
+
+#if CFG_UI
+extern int ui_docommands(char *buf);
+#endif
+
+/* *********************************************************************
+ * data
+ ********************************************************************* */
+
+const char *bootvar_device = "BOOT_DEVICE";
+const char *bootvar_file = "BOOT_FILE";
+const char *bootvar_flags = "BOOT_FLAGS";
+
+cfe_loadargs_t cfe_loadargs;
+
+/* *********************************************************************
+ * splitpath(path,devname,filename)
+ *
+ * Split a path name (a boot path, in the form device:filename)
+ * into its parts
+ *
+ * Input parameters:
+ * path - pointer to path string
+ * devname - receives pointer to device name
+ * filename - receives pointer to file name
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void splitpath(char *path,char **devname,char **filename)
+{
+ char *x;
+
+ *devname = NULL;
+ *filename = NULL;
+
+ x = strchr(path,':');
+
+ if (!x) {
+ *devname = NULL; /* path consists of device name */
+ *filename = path;
+ }
+ else {
+ *x++ = '\0'; /* have both device and file name */
+ *filename = x;
+ *devname = path;
+ }
+}
+
+
+/* *********************************************************************
+ * cfe_go(la)
+ *
+ * Starts a previously loaded program. cfe_loadargs.la_entrypt
+ * must be set to the entry point of the program to be started
+ *
+ * Input parameters:
+ * la - loader args
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_go(cfe_loadargs_t *la)
+{
+ if (la->la_entrypt == 0) {
+ xprintf("No program has been loaded.\n");
+ return;
+ }
+
+#if CFG_NETWORK
+ if (!(la->la_flags & LOADFLG_NOCLOSE)) {
+ if (net_getparam(NET_DEVNAME)) {
+ xprintf("Closing network.\n");
+ net_uninit();
+ }
+ }
+#endif
+
+ xprintf("Starting program at 0x%p\n",la->la_entrypt);
+
+ cfe_start(la->la_entrypt);
+}
+
+
+/* *********************************************************************
+ * cfe_boot(la)
+ *
+ * Bootstrap the system.
+ *
+ * Input parameters:
+ * la - loader arguments
+ *
+ * Return value:
+ * error, or does not return
+ ********************************************************************* */
+int cfe_boot(char *ldrname,cfe_loadargs_t *la)
+{
+ int res;
+
+ la->la_entrypt = 0;
+
+ if (la->la_flags & LOADFLG_NOISY) {
+ xprintf("Loading: ");
+ }
+
+ res = cfe_load_program(ldrname,la);
+
+ if (res < 0) {
+ if (la->la_flags & LOADFLG_NOISY) {
+ xprintf("Failed.\n");
+ }
+ return res;
+ }
+
+ /*
+ * Special case: If loading a batch file, just do the commands here
+ * and return. For batch files we don't want to set up the
+ * environment variables.
+ */
+
+ if (la->la_flags & LOADFLG_BATCH) {
+#if CFG_UI
+ ui_docommands((char *) la->la_entrypt);
+#endif
+ return 0;
+ }
+
+ /*
+ * Otherwise set up for running a real program.
+ */
+
+ if (la->la_flags & LOADFLG_NOISY) {
+ xprintf("Entry at 0x%p\n",la->la_entrypt);
+ }
+
+ /*
+ * Set up the environment variables for the bootstrap
+ */
+
+ if (la->la_device) {
+ env_setenv(bootvar_device,la->la_device,ENV_FLG_BUILTIN);
+ }
+ else {
+ env_delenv(bootvar_device);
+ }
+
+ if (la->la_filename) {
+ env_setenv(bootvar_file,la->la_filename,ENV_FLG_BUILTIN);
+ }
+ else {
+ env_delenv(bootvar_file);
+ }
+
+ if (la->la_options) {
+ env_setenv(bootvar_flags,la->la_options,ENV_FLG_BUILTIN);
+ }
+ else {
+ env_delenv(bootvar_flags);
+ }
+
+ /*
+ * Banzai! Run the program.
+ */
+
+ if ((la->la_flags & LOADFLG_EXECUTE) &&
+ (la->la_entrypt != 0)) {
+ cfe_go(la);
+ }
+
+ return 0;
+}
+
diff --git a/cfe/cfe/main/cfe_console.c b/cfe/cfe/main/cfe_console.c
new file mode 100755
index 0000000..a9464f1
--- /dev/null
+++ b/cfe/cfe/main/cfe_console.c
@@ -0,0 +1,1190 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Console Interface File: cfe_console.c
+ *
+ * This module contains high-level routines for dealing with
+ * the console (TTY-style) device.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include <stdarg.h>
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_error.h"
+#include "env_subr.h"
+#include "cfe_console.h"
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+
+/*
+ * Escape sequences:
+ *
+ * Sequence Descr Emulator
+ *
+ * ESC [ A UP xterm
+ * ESC [ B DOWN xterm
+ * ESC [ C RIGHT xterm
+ * ESC [ D LEFT xterm
+ *
+ * ESC O P F1 xterm
+ * ESC O Q F2 xterm
+ * ESC O R F3 xterm
+ * ESC O S F4 xterm
+ *
+ * ESC [ 1 1 ~ F1 teraterm
+ * ESC [ 1 2 ~ F2 teraterm
+ * ESC [ 1 3 ~ F3 teraterm
+ * ESC [ 1 4 ~ F4 teraterm
+ *
+ * ESC [ 1 5 ~ F5 xterm,teraterm
+ * ESC [ 1 7 ~ F6 xterm,teraterm
+ * ESC [ 1 8 ~ F7 xterm,teraterm
+ * ESC [ 1 9 ~ F8 xterm,teraterm
+ * ESC [ 2 0 ~ F9 xterm,teraterm
+ * ESC [ 2 1 ~ F10 xterm,teraterm
+ * ESC [ 2 3 ~ F11 xterm,teraterm
+ * ESC [ 2 4 ~ F12 xterm,teraterm
+ *
+ * ESC [ 5 ~ PGUP xterm
+ * ESC [ 6 ~ PGDN xterm
+ * ESC [ F HOME xterm
+ * ESC [ H END xterm
+ *
+ * ESC [ 2 ~ HOME teraterm
+ * ESC [ 3 ~ PGUP teraterm
+ * ESC [ 5 ~ END teraterm
+ * ESC [ 6 ~ PGDN teraterm
+ *
+ */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+
+#define CTRL(x) ((x)-'@')
+
+#define GETCHAR(x) while (console_read(&(x),1) != 1) { POLL(); }
+
+#define XTERM 0
+#define TERATERM 1
+
+#define MAXSAVELINES 30
+#define MSGQUEUEMAX 10 /* number of chunks of log to keep */
+#define MSGQUEUESIZE 256 /* size of each chunk of console log */
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct msgqueue_s { /* saved console log message */
+ queue_t link;
+ int len;
+ char data[MSGQUEUESIZE];
+} msgqueue_t;
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+#if !CFG_MINIMAL_SIZE
+int console_nextsave = 0;
+char *console_savedlines[MAXSAVELINES] = {0};
+static char *console_killbuffer = NULL;
+queue_t console_msgq = {&console_msgq,&console_msgq};
+static int console_buffer_flg = 0;
+static int console_mode = XTERM;
+
+static void console_flushbuffer(void);
+static void console_save(unsigned char *buffer,int length);
+
+#endif
+
+#if defined(CONFIG_MIPS_BRCM)
+int g_console_abort = 0;
+#endif
+int console_handle = -1;
+static int console_xprint(const char *str);
+char *console_name = NULL;
+static int console_inreadline = 0;
+static int console_redisplay = 0;
+
+/* *********************************************************************
+ * console_log(tmplt,...)
+ *
+ * Sort of like printf, but used during things that might be
+ * called in the polling loop. If you print out a message
+ * using this call and it happens to be printed while processing
+ * the console "readline" loop, the readline and the associated
+ * prompt will be redisplayed. Don't include the \r\n in the
+ * string to be displayed.
+ *
+ * Input parameters:
+ * tmplt, ... - printf parameters
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void console_log(const char *tmplt,...)
+{
+ char buffer[256];
+ va_list marker;
+ int count;
+
+ va_start(marker,tmplt);
+ count = xvsprintf(buffer,tmplt,marker);
+ va_end(marker);
+ xprintf("\r%s\033[J\r\n",buffer);
+
+ if (console_inreadline) console_redisplay = 1;
+}
+
+/* *********************************************************************
+ * console_open(name)
+ *
+ * Open the specified device and make it the console
+ *
+ * Input parameters:
+ * name - name of device
+ *
+ * Return value:
+ * 0 if ok, else return code.
+ * console_handle contains the console's handle
+ ********************************************************************* */
+
+int console_open(char *name)
+{
+#if CFG_MINIMAL_SIZE
+ if (console_handle != -1) {
+ console_close();
+ }
+
+ console_handle = cfe_open(name);
+ if (console_handle < 0) return CFE_ERR_DEVNOTFOUND;
+
+#else
+
+ int flushbuf;
+
+ console_name = NULL;
+
+ if (console_handle != -1) {
+ console_close();
+ }
+
+ flushbuf = console_buffer_flg;
+ console_buffer_flg = 0;
+
+ console_handle = cfe_open(name);
+ if (console_handle < 0) return CFE_ERR_DEVNOTFOUND;
+
+ console_name = name;
+ if (flushbuf) console_flushbuffer();
+#endif
+
+ return 0;
+}
+
+/* *********************************************************************
+ * console_close()
+ *
+ * Close the console device
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+int console_close(void)
+{
+ if (console_handle != -1) {
+ cfe_close(console_handle);
+ }
+
+ console_handle = -1;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * console_read(buffer,length)
+ *
+ * Read characters from the console.
+ *
+ * Input parameters:
+ * buffer - pointer to buffer to receive characters
+ * length - total size of the buffer
+ *
+ * Return value:
+ * number of characters received, or <0 if error code
+ ********************************************************************* */
+
+int console_read(char *buffer,int length)
+{
+ if (console_handle == -1) return -1;
+
+ return cfe_read(console_handle,(unsigned char*)buffer,length);
+}
+
+
+/* *********************************************************************
+ * console_write(buffer,length)
+ *
+ * Write text to the console. If the console is not open and
+ * we're "saving" text, put the text on the in-memory queue
+ *
+ * Input parameters:
+ * buffer - pointer to data
+ * length - number of characters to write
+ *
+ * Return value:
+ * number of characters written or <0 if error
+ ********************************************************************* */
+
+int console_write(char *buffer,int length)
+{
+ int res;
+
+#if !CFG_MINIMAL_SIZE
+ /*
+ * Buffer text if requested
+ */
+ if (console_buffer_flg) {
+ console_save(buffer,length);
+ return length;
+ }
+#endif
+
+ /*
+ * Do nothing if no console
+ */
+
+ if (console_handle == -1) return -1;
+
+ /*
+ * Write text to device
+ */
+
+ for (;;) {
+ res = cfe_write(console_handle,(unsigned char*)buffer,length);
+ if (res < 0) break;
+ buffer += res;
+ length -= res;
+ if (length == 0) break;
+ }
+
+ if (res < 0) return -1;
+ return 0;
+}
+
+/* *********************************************************************
+ * console_status()
+ *
+ * Return the status of input for the console.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if no characters are available
+ * 1 if characters are available.
+ ********************************************************************* */
+
+int console_status(void)
+{
+ if (console_handle == -1) return 0;
+
+ return cfe_inpstat(console_handle);
+}
+
+/* *********************************************************************
+ * console_xprint(str)
+ *
+ * printf callback for the console device. the "xprintf"
+ * routine ends up calling this. This routine also cooks the
+ * output, turning "\n" into "\r\n"
+ *
+ * Input parameters:
+ * str - string to write
+ *
+ * Return value:
+ * number of characters written
+ ********************************************************************* */
+
+static int console_xprint(const char *str)
+{
+ int count = 0;
+ int len;
+ const char *p;
+
+ /* Convert CR to CRLF as we write things out */
+
+ while ((p = strchr(str,'\n'))) {
+ console_write((char*)str,p-str);
+ console_write("\r\n",2);
+ count += (p-str);
+ str = p + 1;
+ }
+
+ len = strlen(str);
+ console_write((char*)str, len);
+ count += len;
+
+ return count;
+}
+
+
+/* *********************************************************************
+ * console_readline_noedit(str,len)
+ *
+ * A simple 'gets' type routine for the console. We support
+ * backspace and carriage return. No line editing support here,
+ * this routine is used in places where we don't want it.
+ *
+ * Input parameters:
+ * prompt - prompt string
+ * str - pointer to user buffer
+ * len - length of user buffer
+ *
+ * Return value:
+ * number of characters read (terminating newline is not
+ * placed in the buffer)
+ ********************************************************************* */
+
+int console_readline_noedit(char *prompt,char *str,int len)
+{
+ int reading = 1;
+ char ch;
+ int res = -1;
+ int idx = 0;
+
+ console_inreadline++;
+
+ if (prompt && *prompt) console_write(prompt,strlen(prompt));
+
+ POLL();
+ while (reading) {
+
+ /*
+ * If someone used console_log (above) or hit Control-C (below),
+ * redisplay the prompt and the string we've got so far.
+ */
+
+ if (console_redisplay) {
+ if (prompt && *prompt) console_write(prompt,strlen(prompt));
+ console_write(str,idx);
+ console_redisplay = 0;
+ continue;
+ }
+
+#if defined(CONFIG_MIPS_BRCM)
+
+ /*
+ * If a background process has set the global g_console_abort flag, stop
+ * reading from the keyboard.
+ */
+
+ if (g_console_abort) {
+ g_console_abort = 0;
+ break;
+ }
+
+#endif
+
+ /*
+ * if nobody's typed anything, keep polling
+ */
+
+ if (console_status() == 0) {
+ POLL();
+ continue;
+ }
+
+ /*
+ * Get the char from the keyboard
+ */
+
+ res = console_read(&ch,1);
+ if (res < 0) break;
+ if (res == 0) continue;
+
+ /*
+ * And dispatch it
+ */
+
+ switch (ch) {
+ case 3: /* Ctrl-C */
+ console_write("^C\r\n",4);
+ console_redisplay = 1;
+ idx = 0;
+ break;
+ case 0x7f:
+ case '\b':
+ if (idx > 0) {
+ idx--;
+ console_write("\b \b",3);
+ }
+ break;
+ case 21: /* Ctrl-U */
+ while (idx > 0) {
+ idx--;
+ console_write("\b \b",3);
+ }
+ break;
+ case '\r':
+ case '\n':
+ console_write("\r\n",2);
+ reading = 0;
+ break;
+ default:
+ if (ch >= ' ') {
+ if (idx < (len-1)) {
+ str[idx] = ch;
+ idx++;
+ console_write(&ch,1);
+ }
+ }
+ break;
+ }
+ }
+ POLL();
+
+ console_inreadline--;
+
+ str[idx] = 0;
+ return idx;
+}
+
+
+/* *********************************************************************
+ * cfe_set_console(name)
+ *
+ * This routine is usually called from the BSP's initialization
+ * module to set up the console device. We set the xprintf
+ * callback and open the console device. If we open a special
+ * magic console device (CFE_BUFFER_CONSOLE) the console subsystem
+ * will buffer text instead. A later call to cfe_set_console
+ * with a real console name will cause this text to be flushed.
+ *
+ * Input parameters:
+ * name - name of console device
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int cfe_set_console(char *name)
+{
+ xprinthook = console_xprint;
+
+#if !CFG_MINIMAL_SIZE
+ if (strcmp(name,CFE_BUFFER_CONSOLE) == 0) {
+ console_buffer_flg = 1;
+ return 0;
+ }
+#endif
+
+ if (name) {
+ int res;
+ res = env_setenv("BOOT_CONSOLE",name,
+ ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
+ return console_open(name);
+ }
+ return -1;
+}
+
+#if !CFG_MINIMAL_SIZE
+
+/* *********************************************************************
+ * console_flushbuffer()
+ *
+ * Flush queued (saved) console messages to the real console
+ * device. This is used if we need to delay console
+ * initialization until after other devices are initialized,
+ * for example, with a VGA console that won't work until
+ * after PCI initialization.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void console_flushbuffer(void)
+{
+ msgqueue_t *msg;
+ char *buffer;
+ int length;
+ int res;
+
+ /*
+ * Remove console messages from the queue
+ */
+
+ while ((msg = (msgqueue_t *) q_deqnext(&console_msgq))) {
+
+ buffer = msg->data;
+ length = msg->len;
+ res = 0;
+
+ /*
+ * Write each message to the console
+ */
+
+ for (;;) {
+ res = cfe_write(console_handle,buffer,length);
+ if (res < 0) break;
+ buffer += res;
+ length -= res;
+ if (length == 0) break;
+ }
+
+ /*
+ * Free the storage
+ */
+
+ KFREE(msg);
+ }
+}
+
+
+/* *********************************************************************
+ * console_save(buffer,length)
+ *
+ * This is used when we want to generate console output
+ * before the device is initialized. The console_save
+ * routine saves a copy of the log messages in a queue
+ * for later retrieval when the console device is open.
+ *
+ * Input parameters:
+ * buffer - message text to save
+ * length - number of bytes
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void console_save(unsigned char *buffer,int length)
+{
+ msgqueue_t *msg;
+
+ /*
+ * Get a pointer to the last message in the queue. If
+ * it's full, preprare to allocate a new one
+ */
+
+ msg = (msgqueue_t *) console_msgq.q_prev;
+ if (q_isempty(&(console_msgq)) || (msg->len == MSGQUEUESIZE)) {
+ msg = NULL;
+ }
+
+ /*
+ * Stuff characters into message chunks till we're done
+ */
+
+ while (length) {
+
+ /*
+ * New chunk
+ */
+ if (msg == NULL) {
+
+ msg = (msgqueue_t *) KMALLOC(sizeof(msgqueue_t),0);
+ if (msg == NULL) return;
+ msg->len = 0;
+ q_enqueue(&console_msgq,(queue_t *) msg);
+
+ /*
+ * Remove chunks to prevent chewing too much memory
+ */
+
+ while (q_count(&console_msgq) > MSGQUEUEMAX) {
+ msgqueue_t *dropmsg;
+ dropmsg = (msgqueue_t *) q_deqnext(&console_msgq);
+ if (dropmsg) KFREE(dropmsg);
+ }
+ }
+
+ /*
+ * Save text. If we run off the end of the buffer, prepare
+ * to allocate a new one
+ */
+ msg->data[msg->len++] = *buffer++;
+ length--;
+ if (msg->len == MSGQUEUESIZE) msg = NULL;
+ }
+}
+
+
+/* *********************************************************************
+ * console_readnum(num,ch)
+ *
+ * Read digits from the console until we get a non-digit. This
+ * is used to process escape sequences like ESC [ digits ~
+ *
+ * Input parameters:
+ * num - where to put returned number
+ * ch - pointer to character that starts sequence, returns
+ * character that terminated sequence
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void console_readnum(int *num,char *ch)
+{
+ int total = 0;
+
+ for (;;) {
+ total = (total * 10) + (*ch - '0');
+ while (console_read(ch,1) != 1) { POLL(); }
+ if (!((*ch >= '0') && (*ch <= '9'))) break;
+ }
+
+ *num = total;
+}
+
+
+/* *********************************************************************
+ * console_readkey(void)
+ *
+ * Very simple ANSI escape sequence parser, returns virtual
+ * key codes for function keys, arrows, etc.
+ *
+ * Hold your lunch, three levels of nested switch statements! :-)
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * virtual key code
+ ********************************************************************* */
+
+int console_readkey(void)
+{
+ unsigned char ch;
+ int num;
+
+ GETCHAR(ch);
+
+ switch (ch) {
+ case VKEY_ESC:
+ GETCHAR(ch);
+ switch (ch) {
+ case 'O':
+ GETCHAR(ch);
+ switch (ch) {
+ case 'P':
+ return VKEY_F1;
+ case 'Q':
+ return VKEY_F2;
+ case 'R':
+ return VKEY_F3;
+ case 'S':
+ return VKEY_F4;
+ }
+ return (int)ch;
+
+ case '[':
+ GETCHAR(ch);
+ if ((ch >= '0') && (ch <= '9')) {
+ console_readnum(&num,&ch);
+ if (ch == '~') {
+ switch (num) {
+ case 2:
+ return VKEY_HOME;
+ case 3:
+ return VKEY_PGUP;
+ case 5:
+ if (console_mode == XTERM) return VKEY_PGUP;
+ return VKEY_END;
+ case 6:
+ if (console_mode == XTERM) return VKEY_PGDN;
+ return VKEY_PGDN;
+ case 11:
+ return VKEY_F1;
+ case 12:
+ return VKEY_F2;
+ case 13:
+ return VKEY_F3;
+ case 14:
+ return VKEY_F4;
+ case 15:
+ return VKEY_F5;
+ case 17:
+ return VKEY_F6;
+ case 18:
+ return VKEY_F7;
+ case 19:
+ return VKEY_F8;
+ case 20:
+ return VKEY_F9;
+ case 21:
+ return VKEY_F10;
+ case 23:
+ return VKEY_F11;
+ case 24:
+ return VKEY_F12;
+ }
+ return (int)ch;
+ }
+ }
+ else {
+ switch (ch) {
+ case 'A':
+ return VKEY_UP;
+ case 'B':
+ return VKEY_DOWN;
+ case 'C':
+ return VKEY_RIGHT;
+ case 'D':
+ return VKEY_LEFT;
+ case 'F':
+ return VKEY_HOME;
+ case 'H':
+ return VKEY_END;
+ default:
+ return (int) ch;
+ }
+ }
+ default:
+ return (int)ch;
+
+ }
+ default:
+ return (int) ch;
+ }
+}
+
+
+/* *********************************************************************
+ * console_xxx(...)
+ *
+ * Various small routines to write out cursor control sequences.
+ *
+ * Input parameters:
+ * # of iterations, if necessary
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void console_backspace(int n)
+{
+ int t;
+
+ for (t = 0; t < n; t++) console_write("\b",1);
+}
+
+static void console_whiteout(int n)
+{
+ int t;
+
+ for (t = 0; t < n; t++) console_write(" ",1);
+ for (t = 0; t < n; t++) console_write("\b",1);
+}
+
+
+static void console_eraseeol(void)
+{
+ console_write("\033[K",3);
+}
+
+static void console_crlf(void)
+{
+ console_write("\r\n",2);
+}
+
+/* *********************************************************************
+ * console_readline(str,len)
+ *
+ * A simple 'gets' type routine for the console, with line
+ * editing support.
+ *
+ * Input parameters:
+ * prompt - prompt string
+ * str - pointer to user buffer
+ * len - length of user buffer
+ *
+ * Return value:
+ * number of characters read (terminating newline is not
+ * placed in the buffer)
+ ********************************************************************* */
+
+int console_readline(char *prompt,char *str,int maxlen)
+{
+ int reading = 1;
+ int ch;
+ int idx = 0;
+ int len = 0;
+ int t;
+ int klen;
+ int recall;
+ int nosave = 0;
+ char *x;
+ char env[10];
+
+ console_inreadline++;
+ recall = console_nextsave;
+
+ if (console_savedlines[console_nextsave]) {
+ KFREE(console_savedlines[console_nextsave]);
+ console_savedlines[console_nextsave] = NULL;
+ }
+ console_savedlines[console_nextsave] = strdup("");
+
+ if (prompt && *prompt) console_write(prompt,strlen(prompt));
+
+ POLL();
+ while (reading) {
+
+ /*
+ * If someone used console_log (above) or hit Control-C (below),
+ * redisplay the prompt and the string we've got so far.
+ */
+
+ if (console_redisplay) {
+ if (prompt && *prompt) console_write(prompt,strlen(prompt));
+ console_write(str,idx);
+ console_redisplay = 0;
+ continue;
+ }
+
+#if defined(CONFIG_MIPS_BRCM)
+
+ /*
+ * If a background process has set the global g_console_abort flag, stop
+ * reading from the keyboard.
+ */
+
+ if (g_console_abort) {
+ g_console_abort = 0;
+ break;
+ }
+
+#endif
+
+ /*
+ * if nobody's typed anything, keep polling
+ */
+
+ if (console_status() == 0) {
+ POLL();
+ continue;
+ }
+
+ /*
+ * Get the char from the keyboard
+ */
+
+ ch = console_readkey();
+ if (ch < 0) break;
+ if (ch == 0) continue;
+
+ /*
+ * And dispatch it. Lots of yucky character manipulation follows
+ */
+
+ switch (ch) {
+ case CTRL('C'): /* Ctrl-C - cancel line */
+ console_write("^C\r\n",4);
+ console_redisplay = 1;
+ nosave = 1;
+ idx = 0;
+ break;
+
+ case 0x7f: /* Backspace, Delete */
+ case CTRL('H'):
+ if (idx > 0) {
+ nosave = 0;
+ len--;
+ idx--;
+ console_write("\b",1);
+ if (len != idx) {
+ for (t = idx; t < len; t++) str[t] = str[t+1];
+ console_write(&str[idx],len-idx);
+ console_whiteout(1);
+ console_backspace(len-idx);
+ }
+ else {
+ console_whiteout(1);
+ }
+ }
+ break;
+
+ case CTRL('D'): /* Ctrl-D */
+ if ((idx >= 0) && (len != idx)) {
+ nosave = 0;
+ len--;
+ for (t = idx; t < len; t++) str[t] = str[t+1];
+ console_write(&str[idx],len-idx);
+ console_whiteout(1);
+ console_backspace(len-idx);
+ }
+ break;
+
+ case CTRL('B'): /* cursor left */
+ case VKEY_LEFT:
+ if (idx > 0) {
+ idx--;
+ console_backspace(1);
+ }
+ break;
+
+ case CTRL('F'): /* cursor right */
+ case VKEY_RIGHT:
+ if (idx < len) {
+ console_write(&str[idx],1);
+ idx++;
+ }
+ break;
+
+ case CTRL('A'): /* cursor to BOL */
+ console_backspace(idx);
+ idx = 0;
+ break;
+
+ case CTRL('E'): /* cursor to EOL */
+ if (len-idx > 0) console_write(&str[idx],len-idx);
+ idx = len;
+ break;
+
+ case CTRL('K'): /* Kill to EOL */
+ if (idx != len) {
+ str[len] = '\0';
+ if (console_killbuffer) KFREE(console_killbuffer);
+ console_killbuffer = strdup(&str[idx]);
+ console_whiteout(len-idx);
+ len = idx;
+ nosave = 0;
+ }
+ break;
+
+ case CTRL('Y'): /* Yank killed data */
+ if (console_killbuffer == NULL) break;
+ klen = strlen(console_killbuffer);
+ if (klen == 0) break;
+ if (len + klen > maxlen) break;
+ nosave = 0;
+ for (t = len + klen; t > idx; t--) {
+ str[t-1] = str[t-klen-1];
+ }
+ for (t = 0; t < klen; t++) str[t+idx] = console_killbuffer[t];
+ len += klen;
+ console_write(&str[idx],len-idx);
+ idx += klen;
+ console_backspace(len-idx-1);
+ break;
+
+ case CTRL('R'): /* Redisplay line */
+ str[len] = 0;
+ console_crlf();
+ console_write(prompt,strlen(prompt));
+ console_write(str,len);
+ console_backspace(len-idx);
+ break;
+
+ case CTRL('U'): /* Cancel line */
+ console_backspace(idx);
+ console_eraseeol();
+ if (len > 0) nosave = 1;
+ idx = 0;
+ len = 0;
+ break;
+
+ case CTRL('M'): /* terminate */
+ case CTRL('J'):
+ console_crlf();
+ reading = 0;
+ break;
+
+ case CTRL('P'):
+ case VKEY_UP: /* recall previous line */
+ t = recall;
+ t--;
+ if (t < 0) t = MAXSAVELINES-1;
+ if (console_savedlines[t] == NULL) break;
+ recall = t;
+ console_backspace(idx);
+ strcpy(str,console_savedlines[recall]);
+ len = idx = strlen(console_savedlines[recall]);
+ console_eraseeol();
+ console_write(str,len);
+ nosave = (t == ((console_nextsave - 1) % MAXSAVELINES));
+ break;
+
+ case CTRL('N'):
+ case VKEY_DOWN: /* Recall next line */
+ t = recall;
+ t++;
+ if (t == MAXSAVELINES) t = 0;
+ if (console_savedlines[t] == NULL) break;
+ recall = t;
+ console_backspace(idx);
+ strcpy(str,console_savedlines[recall]);
+ len = idx = strlen(console_savedlines[recall]);
+ console_eraseeol();
+ console_write(str,len);
+ nosave = 1;
+ break;
+
+ case VKEY_F1:
+ case VKEY_F2:
+ case VKEY_F3:
+ case VKEY_F4:
+ case VKEY_F5:
+ case VKEY_F6:
+ case VKEY_F7:
+ case VKEY_F8:
+ case VKEY_F9:
+ case VKEY_F10:
+ case VKEY_F11:
+ case VKEY_F12:
+ sprintf(env,"F%d",ch-VKEY_F1+1);
+ x = env_getenv(env);
+ if (x) {
+ console_backspace(idx);
+ strcpy(str,x);
+ idx = len = strlen(str);
+ console_eraseeol();
+ console_write(str,len);
+ console_crlf();
+ reading = 0;
+ nosave = 1;
+ }
+ /*
+ * If F12 is undefined, it means "repeat last command"
+ */
+ if (ch == VKEY_F12) {
+ t = recall;
+ t--;
+ if (t < 0) t = MAXSAVELINES-1;
+ if (console_savedlines[t] == NULL) break;
+ recall = t;
+ console_backspace(idx);
+ strcpy(str,console_savedlines[recall]);
+ len = idx = strlen(console_savedlines[recall]);
+ console_eraseeol();
+ console_write(str,len);
+ console_crlf();
+ reading = 0;
+ nosave = 1;
+ }
+ break;
+
+ default: /* insert character */
+ if (ch >= ' ') {
+ if (idx < (maxlen-1)) {
+ nosave = 0;
+ for (t = len; t > idx; t--) {
+ str[t] = str[t-1];
+ }
+ str[idx] = ch;
+ len++;
+ if (len != idx) {
+ console_write(&str[idx],len-idx);
+ console_backspace(len-idx-1);
+ }
+ idx++;
+ }
+ }
+ break;
+ }
+ }
+ POLL();
+
+ console_inreadline--;
+
+ str[len] = 0;
+
+ if ((len != 0) && !nosave) {
+ if (console_savedlines[console_nextsave]) {
+ KFREE(console_savedlines[console_nextsave]);
+ }
+ console_savedlines[console_nextsave] = strdup(str);
+ console_nextsave++;
+ if (console_nextsave == MAXSAVELINES) console_nextsave = 0;
+ }
+
+ return len;
+}
+
+#else /* CFG_MINIMAL_SIZE */
+/* *********************************************************************
+ * console_readline(str,len)
+ *
+ * A simple 'gets' type routine for the console,
+ * just calls the "noedit" variant for minimal code
+ * size builds.
+ *
+ * Input parameters:
+ * prompt - prompt string
+ * str - pointer to user buffer
+ * len - length of user buffer
+ *
+ * Return value:
+ * number of characters read (terminating newline is not
+ * placed in the buffer)
+ ********************************************************************* */
+
+int console_readline(char *prompt,char *str,int len)
+{
+ return console_readline_noedit(prompt,str,len);
+}
+
+#endif
diff --git a/cfe/cfe/main/cfe_devfuncs.c b/cfe/cfe/main/cfe_devfuncs.c
new file mode 100755
index 0000000..c3ab905
--- /dev/null
+++ b/cfe/cfe/main/cfe_devfuncs.c
@@ -0,0 +1,279 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device Function stubs File: cfe_devfuncs.c
+ *
+ * This module contains device function stubs (small routines to
+ * call the standard "iocb" interface entry point to CFE).
+ * There should be one routine here per iocb function call.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+
+extern int cfe_iocb_dispatch(cfe_iocb_t *iocb);
+
+static int cfe_strlen(char *name)
+{
+ int count = 0;
+
+ while (*name) {
+ count++;
+ name++;
+ }
+
+ return count;
+}
+
+int cfe_open(char *name)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_OPEN;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = 0;
+ iocb.plist.iocb_buffer.buf_ptr = (unsigned char*)name;
+ iocb.plist.iocb_buffer.buf_length = cfe_strlen(name);
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status < 0) ? iocb.iocb_status : iocb.iocb_handle;
+}
+
+int cfe_close(int handle)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_CLOSE;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = 0;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status);
+
+}
+
+int cfe_readblk(int handle,cfe_offset_t offset,unsigned char *buffer,int length)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_READ;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = offset;
+ iocb.plist.iocb_buffer.buf_ptr = buffer;
+ iocb.plist.iocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status < 0) ? iocb.iocb_status : iocb.plist.iocb_buffer.buf_retlen;
+}
+
+int cfe_read(int handle,unsigned char *buffer,int length)
+{
+ return cfe_readblk(handle,0,buffer,length);
+}
+
+
+int cfe_writeblk(int handle,cfe_offset_t offset,unsigned char *buffer,int length)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_WRITE;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = offset;
+ iocb.plist.iocb_buffer.buf_ptr = buffer;
+ iocb.plist.iocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status < 0) ? iocb.iocb_status : iocb.plist.iocb_buffer.buf_retlen;
+}
+
+int cfe_write(int handle,unsigned char *buffer,int length)
+{
+ return cfe_writeblk(handle,0,buffer,length);
+}
+
+
+int cfe_ioctl(int handle,unsigned int ioctlnum,
+ unsigned char *buffer,int length,int *retlen,
+ cfe_offset_t offset)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_IOCTL;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = offset;
+ iocb.plist.iocb_buffer.buf_ioctlcmd = (cfe_offset_t) ioctlnum;
+ iocb.plist.iocb_buffer.buf_ptr = buffer;
+ iocb.plist.iocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&iocb);
+
+ if (retlen) *retlen = iocb.plist.iocb_buffer.buf_retlen;
+ return iocb.iocb_status;
+}
+
+int cfe_inpstat(int handle)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_INPSTAT;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_inpstat_t);
+ iocb.plist.iocb_inpstat.inp_status = 0;
+
+ cfe_iocb_dispatch(&iocb);
+
+ if (iocb.iocb_status < 0) return iocb.iocb_status;
+
+ return iocb.plist.iocb_inpstat.inp_status;
+
+}
+
+long long cfe_getticks(void)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_FW_GETTIME;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_time_t);
+ iocb.plist.iocb_time.ticks = 0;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return iocb.plist.iocb_time.ticks;
+
+}
+
+int cfe_getenv(char *name,char *dest,int destlen)
+{
+ cfe_iocb_t iocb;
+
+ *dest = NULL;
+
+ iocb.iocb_fcode = CFE_CMD_ENV_GET;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_envbuf_t);
+ iocb.plist.iocb_envbuf.enum_idx = 0;
+ iocb.plist.iocb_envbuf.name_ptr = (unsigned char*)name;
+ iocb.plist.iocb_envbuf.name_length = strlen(name)+1;
+ iocb.plist.iocb_envbuf.val_ptr = (unsigned char*)dest;
+ iocb.plist.iocb_envbuf.val_length = destlen;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return iocb.iocb_status;
+}
+
+int cfe_exit(int warm,int code)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_FW_RESTART;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = warm ? CFE_FLG_WARMSTART : 0;
+ iocb.iocb_psize = sizeof(iocb_exitstat_t);
+ iocb.plist.iocb_exitstat.status = code;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status);
+
+}
+
+int cfe_flushcache(int flg)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_FW_FLUSHCACHE;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = flg;
+ iocb.iocb_psize = 0;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return iocb.iocb_status;
+}
+
+int cfe_getdevinfo(char *name)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_GETINFO;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = 0;
+ iocb.plist.iocb_buffer.buf_ptr = (unsigned char*)name;
+ iocb.plist.iocb_buffer.buf_length = cfe_strlen(name);
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status < 0) ? iocb.iocb_status : (int)iocb.plist.iocb_buffer.buf_devflags;
+}
diff --git a/cfe/cfe/main/cfe_error.c b/cfe/cfe/main/cfe_error.c
new file mode 100644
index 0000000..198e7a4
--- /dev/null
+++ b/cfe/cfe/main/cfe_error.c
@@ -0,0 +1,134 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Error strings File: cfe_error.h
+ *
+ * This file contains a mapping from error codes to strings
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "cfe.h"
+#include "cfe_error.h"
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+
+typedef struct errmap_s {
+ int errcode;
+ const char *string;
+} errmap_t;
+
+/* *********************************************************************
+ * Error code list
+ ********************************************************************* */
+
+errmap_t cfe_errorstrings[] = {
+ {CFE_OK ,"No error"},
+ {CFE_ERR ,"Error"},
+ {CFE_ERR_INV_COMMAND ,"Invalid command"},
+ {CFE_ERR_EOF ,"End of file reached"},
+ {CFE_ERR_IOERR ,"I/O error"},
+ {CFE_ERR_NOMEM ,"Insufficient memory"},
+ {CFE_ERR_DEVNOTFOUND ,"Device not found"},
+ {CFE_ERR_DEVOPEN ,"Device is open"},
+ {CFE_ERR_INV_PARAM ,"Invalid parameter"},
+ {CFE_ERR_ENVNOTFOUND ,"Environment variable not found"},
+ {CFE_ERR_ENVREADONLY ,"Environment variable is read-only"},
+ {CFE_ERR_NOTELF ,"Not an ELF-format executable"},
+ {CFE_ERR_NOT32BIT ,"Not a 32-bit executable"},
+ {CFE_ERR_WRONGENDIAN ,"Executable is wrong-endian"},
+ {CFE_ERR_BADELFVERS ,"Invalid ELF file version"},
+ {CFE_ERR_NOTMIPS ,"Not a MIPS ELF file"},
+ {CFE_ERR_BADELFFMT ,"Invalid ELF file"},
+ {CFE_ERR_BADADDR ,"Section would load outside available DRAM"},
+ {CFE_ERR_FILENOTFOUND ,"File not found"},
+ {CFE_ERR_UNSUPPORTED ,"Unsupported function"},
+ {CFE_ERR_HOSTUNKNOWN ,"Host name unknown"},
+ {CFE_ERR_TIMEOUT ,"Timeout occured"},
+ {CFE_ERR_PROTOCOLERR ,"Network protocol error"},
+ {CFE_ERR_NETDOWN ,"Network is down"},
+ {CFE_ERR_NONAMESERVER ,"No name server configured"},
+ {CFE_ERR_NOHANDLES ,"No more handles"},
+ {CFE_ERR_ALREADYBOUND ,"Already bound"},
+ {CFE_ERR_CANNOTSET ,"Cannot set network parameter"},
+ {CFE_ERR_NOMORE ,"No more enumerated items"},
+ {CFE_ERR_BADFILESYS ,"File system not recognized"},
+ {CFE_ERR_FSNOTAVAIL ,"File system not available"},
+ {CFE_ERR_INVBOOTBLOCK ,"Invalid boot block on disk"},
+ {CFE_ERR_WRONGDEVTYPE ,"Device type is incorrect for boot method"},
+ {CFE_ERR_BBCHECKSUM ,"Boot block checksum is invalid"},
+ {CFE_ERR_BOOTPROGCHKSUM ,"Boot program checksum is invalid"},
+ {CFE_ERR_LDRNOTAVAIL, "Loader is not available"},
+ {CFE_ERR_NOTREADY, "Device is not ready"},
+ {CFE_ERR_GETMEM, "Cannot get memory at specified address"},
+ {CFE_ERR_SETMEM, "Cannot set memory at specified address"},
+ {CFE_ERR_NOTCONN, "Socket is not connected"},
+ {CFE_ERR_ADDRINUSE, "Address is in use"},
+ {0,NULL}};
+
+
+/* *********************************************************************
+ * cfe_errortext(err)
+ *
+ * Returns the text corresponding to a CFE error code
+ *
+ * Input parameters:
+ * err - error code
+ *
+ * Return value:
+ * string description of error
+ ********************************************************************* */
+
+const char *cfe_errortext(int err)
+{
+ errmap_t *e = cfe_errorstrings;
+
+ while (e->string) {
+ if (e->errcode == err) return e->string;
+ e++;
+ }
+
+ return (const char *) "Unknown error";
+}
+
diff --git a/cfe/cfe/main/cfe_fatfs.c b/cfe/cfe/main/cfe_fatfs.c
new file mode 100644
index 0000000..f2fa49f
--- /dev/null
+++ b/cfe/cfe/main/cfe_fatfs.c
@@ -0,0 +1,1983 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * FAT file system File: cfe_fatfs.c
+ *
+ * This module knows how to read files from a FAT formatted
+ * file system (12 or 16 bit fats only for now)
+ *
+ * Eventually, we'll also include support for the FAT Translation
+ * Layer (FTL) on PCMCIA flash file systems.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe_loader.h"
+
+#include "cfe.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define SECTORSIZE 512
+#define DIRENTRYSIZE 32
+#define DIRPERSECTOR (SECTORSIZE/DIRENTRYSIZE)
+
+/*#define _FATFS_DEBUG_*/
+
+/*
+ * Bios Parameter Block offsets and values
+ */
+
+#define BPB_JMPINSTR 0x00
+#define BPB_JMPINSTR_VALUE 0xEB
+#define BPB_JMPINSTR_VALUE2 0xE9
+#define BPB_SEAL 0x1FE
+#define BPB_SEAL_VALUE 0xAA55
+
+#define BPB_BYTESPERSECTOR 0x0B
+#define BPB_SECTORSPERCLUSTER 0x0D
+#define BPB_RESERVEDSECTORS 0x0E
+#define BPB_NUMFATS 0x10
+#define BPB_MAXROOTDIR 0x11
+#define BPB_TOTALSECTORS 0x13
+#define BPB_SECTORSPERFAT 0x16
+#define BPB_SECTORSPERTRACK 0x18
+#define BPB_NUMHEADS 0x1A
+#define BPB_HIDDENSECTORS 0x1C
+#define BPB_SYSTEMID 54
+#define BPB_MEDIADESCRIPTOR 21
+#define BPB_SIGNATURE 38
+#define BPB_SIGNATURE_VALUE1 0x28
+#define BPB_SIGNATURE_VALUE2 0x29
+
+/*
+ * Partition types
+ */
+
+#define PARTTYPE_EMPTY 0
+#define PARTTYPE_FAT12 1
+#define PARTTYPE_FAT16 4
+#define PARTTYPE_FAT16BIG 6
+#define PARTTYPE_FAT32 0x0B
+
+/*
+ * Partition table offsets
+ */
+#define PTABLE_STATUS 0
+#define PTABLE_STARTHEAD 1
+#define PTABLE_STARTSECCYL 2 /* 2 bytes */
+#define PTABLE_TYPE 4
+#define PTABLE_ENDHEAD 5
+#define PTABLE_ENDSECCYL 6 /* 2 bytes */
+#define PTABLE_BOOTSECTOR 8 /* 4 bytes */
+#define PTABLE_NUMSECTORS 12 /* 4 bytes */
+
+#define PTABLE_SIZE 16
+#define PTABLE_COUNT 4
+#define PTABLE_OFFSET (512-2-(PTABLE_COUNT*PTABLE_SIZE))
+
+#define PTABLE_STATUS_ACTIVE 0x80
+
+/*
+ * Directory attributes
+ */
+
+#define ATTRIB_NORMAL 0x00
+#define ATTRIB_READONLY 0x01
+#define ATTRIB_HIDDEN 0x02
+#define ATTRIB_SYSTEM 0x04
+#define ATTRIB_LABEL 0x08
+#define ATTRIB_DIR 0x10
+#define ATTRIB_ARCHIVE 0x20
+
+#define ATTRIB_LFN 0x0F
+
+/*
+ * Macros to read fields in directory & BPB entries
+ */
+
+#define READWORD(buffer,x) (((unsigned int) (buffer)[(x)]) | \
+ (((unsigned int) (buffer)[(x)+1]) << 8))
+
+#define READWORD32(buffer,x) (READWORD(buffer,(x)) | (READWORD(buffer,(x)+2) << 16))
+
+#define READBYTE(buffer,x) ((unsigned int) (buffer)[(x)])
+
+/*
+ * Directory entry offsets and values
+ */
+
+#define DIR_CHECKSUM 13
+#define DIR_FILELENGTH 28
+#define DIR_STARTCLUSTER 26
+#define DIR_ATTRIB 11
+#define DIR_NAMEOFFSET 0
+#define DIR_NAMELEN 8
+#define DIR_EXTOFFSET 8
+#define DIR_EXTLEN 3
+
+#define DIRENTRY_CHECKSUM(e) READBYTE(e,DIR_CHECKSUM)
+#define DIRENTRY_FILELENGTH(e) READWORD32(e,DIR_FILELENGTH)
+#define DIRENTRY_STARTCLUSTER(e) READWORD(e,DIR_STARTCLUSTER)
+#define DIRENTRY_ATTRIB(e) READBYTE(e,DIR_ATTRIB)
+
+#define DIRENTRY_LAST 0
+#define DIRENTRY_DELETED 0xE5
+#define DIRENTRY_PARENTDIR 0x2E
+
+#define DIRENTRY_LFNIDX(e) READBYTE(e,0)
+#define LFNIDX_MASK 0x1F
+#define LFNIDX_END 0x40
+#define LFNIDX_MAX 20
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+/*
+ * Internalized BPB
+ */
+
+typedef struct bpb_s {
+ unsigned int bpb_bytespersector;
+ unsigned int bpb_sectorspercluster;
+ unsigned int bpb_reservedsectors;
+ unsigned int bpb_numfats;
+ unsigned int bpb_maxrootdir;
+ unsigned int bpb_totalsectors;
+ unsigned int bpb_sectorsperfat;
+ unsigned int bpb_sectorspertrack;
+ unsigned int bpb_numheads;
+ unsigned int bpb_hiddensectors;
+} bpb_t;
+
+/*
+ * FAT Filesystem descriptor - contains working information
+ * about an "open" file system
+ */
+
+typedef struct fatfs_s {
+ int fat_fh;
+ int fat_refcnt;
+ bpb_t fat_bpb;
+ int fat_twelvebit;
+ int fat_partstart;
+ uint8_t fat_dirsector[SECTORSIZE];
+ int fat_dirsecnum;
+ uint8_t fat_fatsector[SECTORSIZE];
+ int fat_fatsecnum;
+} fatfs_t;
+
+/*
+ * FAT Chain - describes a series of FAT entries
+ */
+
+typedef struct fatchain_s {
+ int fat_start;
+ uint16_t *fat_entries;
+ int fat_count;
+} fatchain_t;
+
+/*
+ * FAT File descriptor - contains working information
+ * about an open file (including the filesystem info)
+ */
+
+typedef struct fatfile_s {
+ fatfs_t *ff_fat;
+ int ff_filelength;
+ fatchain_t ff_chain;
+ int ff_curpos;
+ int ff_cursector;
+ uint8_t ff_sector[SECTORSIZE];
+} fatfile_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int fatfs_fileop_xinit(void **fsctx,void *filename);
+static int fatfs_fileop_pinit(void **fsctx,void *filename);
+static int fatfs_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int fatfs_fileop_read(void *ref,uint8_t *buf,int len);
+static int fatfs_fileop_write(void *ref,uint8_t *buf,int len);
+static int fatfs_fileop_seek(void *ref,int offset,int how);
+static void fatfs_fileop_close(void *ref);
+static void fatfs_fileop_uninit(void *fsctx);
+
+static int fatfs_check_for_partition_table(fatfs_t *fatfs);
+
+/* *********************************************************************
+ * FAT fileio dispatch table
+ ********************************************************************* */
+
+/*
+ * Raw FAT (no partition table) - used only on floppies
+ */
+
+const fileio_dispatch_t fatfs_fileops = {
+ "rfat",
+ LOADFLG_NOBB,
+ fatfs_fileop_xinit,
+ fatfs_fileop_open,
+ fatfs_fileop_read,
+ fatfs_fileop_write,
+ fatfs_fileop_seek,
+ fatfs_fileop_close,
+ fatfs_fileop_uninit
+};
+
+/*
+ * Partitioned FAT - used on Zip disks, removable hard disks,
+ * hard disks, flash cards, etc.
+ */
+
+const fileio_dispatch_t pfatfs_fileops = {
+ "fat",
+ LOADFLG_NOBB,
+ fatfs_fileop_pinit,
+ fatfs_fileop_open,
+ fatfs_fileop_read,
+ fatfs_fileop_write,
+ fatfs_fileop_seek,
+ fatfs_fileop_close,
+ fatfs_fileop_uninit
+};
+
+
+/* *********************************************************************
+ * fat_readsector(fatfs,sector,numsec,buffer)
+ *
+ * Read one or more sectors from the disk into memory
+ *
+ * Input parameters:
+ * fatfs - fat filesystem descriptor
+ * sector - sector number
+ * numsec - number of sectors to read
+ * buffer - buffer to read sectors into
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_readsector(fatfs_t *fatfs,int sector,int numsec,uint8_t *buffer)
+{
+ int res;
+
+ res = cfe_readblk(fatfs->fat_fh,(sector+fatfs->fat_partstart)*SECTORSIZE,
+ buffer,numsec*SECTORSIZE);
+
+ if (res != numsec*SECTORSIZE) return CFE_ERR_IOERR;
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fat_dumpbpb(bpb)
+ *
+ * Debug function; display fields in a BPB
+ *
+ * Input parameters:
+ * bpb - BIOS parameter block structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#ifdef _FATFS_DEBUG_
+static void fat_dumpbpb(bpb_t *bpb)
+{
+ xprintf("Bytes per sector %d\n",bpb->bpb_bytespersector);
+ xprintf("Sectors per cluster %d\n",bpb->bpb_sectorspercluster);
+ xprintf("Reserved sectors %d\n",bpb->bpb_reservedsectors);
+ xprintf("Number of FATs %d\n",bpb->bpb_numfats);
+ xprintf("Root dir entries %d\n",bpb->bpb_maxrootdir);
+ xprintf("Total sectors %d\n",bpb->bpb_totalsectors);
+ xprintf("Sectors per FAT %d\n",bpb->bpb_sectorsperfat);
+ xprintf("Sectors per track %d\n",bpb->bpb_sectorspertrack);
+ xprintf("Number of heads %d\n",bpb->bpb_numheads);
+ xprintf("Hidden sectors %d\n",bpb->bpb_hiddensectors);
+}
+#endif
+
+/* *********************************************************************
+ * fat_findpart(fatfs)
+ *
+ * For partitioned disks, locate the active partition
+ * and set "fat_partstart" accordingly
+ *
+ * Input parameters:
+ * fatfs - FAT filesystem descriptor
+ *
+ * Return value:
+ * 0 if we found a valid partition table; else error code
+ ********************************************************************* */
+
+static int fat_findpart(fatfs_t *fatfs)
+{
+ uint8_t buffer[SECTORSIZE];
+ uint8_t *part;
+ int res;
+ int idx;
+
+ fatfs->fat_partstart = 0; /* make sure we get real boot sector */
+ res = fat_readsector(fatfs,0,1,buffer);
+ if (res < 0) return res;
+
+ /*
+ * Normally you're supposed to check for a JMP instruction.
+ * At least that's what many people do. Flash MBRs don't start
+ * with JMP instructions, so just look for the seal.
+ *
+ *
+ * if (READBYTE(buffer,BPB_JMPINSTR) != BPB_JMPINSTR_VALUE) {
+ * return CFE_ERR_BADFILESYS;
+ * }
+ */
+
+ /*
+ * Check the seal at the end of th sector
+ */
+
+ if (READWORD(buffer,BPB_SEAL) != BPB_SEAL_VALUE) return CFE_ERR_BADFILESYS;
+
+ /*
+ * Look for an active FAT partition. The partition we want must
+ * be the active one. We do not deal with extended partitions
+ * here. Hey, this is supposed to be boot code!
+ */
+
+ part = &buffer[PTABLE_OFFSET];
+ for (idx = 0; idx < PTABLE_COUNT; idx++) {
+ if ((part[PTABLE_STATUS] == PTABLE_STATUS_ACTIVE) &&
+ ((part[PTABLE_TYPE] == PARTTYPE_FAT12) ||
+ (part[PTABLE_TYPE] == PARTTYPE_FAT16) ||
+ (part[PTABLE_TYPE] == PARTTYPE_FAT16BIG))) {
+ break;
+ }
+
+ part += PTABLE_SIZE;
+ }
+
+ if (idx == PTABLE_COUNT) return CFE_ERR_BADFILESYS;
+
+ /*
+ * The info we want is really just the pointer to the
+ * boot (BPB) sector. Get that and we'll use it for an
+ * offset into the disk later.
+ */
+
+ fatfs->fat_partstart = READWORD32(part,PTABLE_BOOTSECTOR);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fat_readbpb(fatfs)
+ *
+ * Read and internalize the BIOS Parameter Block
+ *
+ * Input parameters:
+ * fatfs - FAT filesystem descriptor
+ *
+ * Return value:
+ * 0 if ok
+ * else error code (usually, BPB is not valid)
+ ********************************************************************* */
+
+static int fat_readbpb(fatfs_t *fatfs)
+{
+ uint8_t buffer[SECTORSIZE];
+ int res;
+
+ res = fat_readsector(fatfs,0,1,buffer);
+ if (res < 0) return res;
+
+ if (READBYTE(buffer,BPB_JMPINSTR) != BPB_JMPINSTR_VALUE) return CFE_ERR_BADFILESYS;
+ if (READWORD(buffer,BPB_SEAL) != BPB_SEAL_VALUE) return CFE_ERR_BADFILESYS;
+
+ fatfs->fat_bpb.bpb_bytespersector = READWORD(buffer,BPB_BYTESPERSECTOR);
+ fatfs->fat_bpb.bpb_sectorspercluster = READBYTE(buffer,BPB_SECTORSPERCLUSTER);
+ fatfs->fat_bpb.bpb_reservedsectors = READWORD(buffer,BPB_RESERVEDSECTORS);
+ fatfs->fat_bpb.bpb_numfats = READBYTE(buffer,BPB_NUMFATS);
+ fatfs->fat_bpb.bpb_maxrootdir = READWORD(buffer,BPB_MAXROOTDIR);
+ fatfs->fat_bpb.bpb_totalsectors = READWORD(buffer,BPB_TOTALSECTORS);
+ fatfs->fat_bpb.bpb_sectorsperfat = READWORD(buffer,BPB_SECTORSPERFAT);
+ fatfs->fat_bpb.bpb_sectorspertrack = READWORD(buffer,BPB_SECTORSPERTRACK);
+ fatfs->fat_bpb.bpb_numheads = READWORD(buffer,BPB_NUMHEADS);
+ fatfs->fat_bpb.bpb_hiddensectors = READWORD(buffer,BPB_HIDDENSECTORS);
+
+ fatfs->fat_twelvebit = 1;
+ if (memcmp(&buffer[0x36],"FAT16 ",8) == 0) fatfs->fat_twelvebit = 0;
+
+ if (fatfs->fat_bpb.bpb_bytespersector != SECTORSIZE) return CFE_ERR_BADFILESYS;
+ if (fatfs->fat_bpb.bpb_numfats > 2) return CFE_ERR_BADFILESYS;
+
+ /*
+ * XXX sanity check other fields
+ */
+
+#ifdef _FATFS_DEBUG_
+ fat_dumpbpb(&(fatfs->fat_bpb));
+#endif
+
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * fat_getentry(fatfs,entry)
+ *
+ * Read a FAT entry. This is more involved than you'd think,
+ * since we have to deal with 12 and 16 (and someday 32) bit FATs,
+ * and the nasty case where a 12-bit FAT entry crosses a sector
+ * boundary.
+ *
+ * Input parameters:
+ * fatfs - FAT filesystem descriptor
+ * entry - index of FAT entry
+ *
+ * Return value:
+ * FAT entry, or <0 if an error occured
+ ********************************************************************* */
+
+static int fat_getfatentry(fatfs_t *fatfs,int entry)
+{
+ int fatsect;
+ int byteoffset;
+ int fatstart;
+ int fatoffset;
+ uint8_t b1,b2,b3;
+ int res;
+
+ fatstart = fatfs->fat_bpb.bpb_reservedsectors;
+
+ if (fatfs->fat_twelvebit) {
+ int odd;
+ odd = entry & 1;
+ byteoffset = ((entry & ~1) * 3) / 2;
+ fatsect = byteoffset / SECTORSIZE;
+ fatoffset = byteoffset % SECTORSIZE;
+
+ if (fatfs->fat_fatsecnum != fatsect) {
+ res = fat_readsector(fatfs,fatsect+fatstart,1,fatfs->fat_fatsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_fatsecnum = fatsect;
+ }
+
+ b1 = fatfs->fat_fatsector[fatoffset];
+
+ if ((fatoffset+1) >= SECTORSIZE) {
+ res = fat_readsector(fatfs,fatsect+1+fatstart,1,fatfs->fat_fatsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_fatsecnum = fatsect+1;
+ fatoffset -= SECTORSIZE;
+ }
+
+ b2 = fatfs->fat_fatsector[fatoffset+1];
+
+ if ((fatoffset+2) >= SECTORSIZE) {
+ res = fat_readsector(fatfs,fatsect+1+fatstart,1,fatfs->fat_fatsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_fatsecnum = fatsect+1;
+ fatoffset -= SECTORSIZE;
+ }
+
+ b3 = fatfs->fat_fatsector[fatoffset+2];
+
+ if (odd) {
+ return ((unsigned int) b3 << 4) + ((unsigned int) (b2 & 0xF0) >> 4);
+ }
+ else {
+ return ((unsigned int) (b2 & 0x0F) << 8) + ((unsigned int) b1);
+ }
+
+ }
+ else {
+ byteoffset = entry * 2;
+ fatsect = byteoffset / SECTORSIZE;
+ fatoffset = byteoffset % SECTORSIZE;
+
+ if (fatfs->fat_fatsecnum != fatsect) {
+ res = fat_readsector(fatfs,fatsect+fatstart,1,fatfs->fat_fatsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_fatsecnum = fatsect;
+ }
+
+ b1 = fatfs->fat_fatsector[fatoffset];
+ b2 = fatfs->fat_fatsector[fatoffset+1];
+ return ((unsigned int) b1) + (((unsigned int) b2) << 8);
+ }
+}
+
+/* *********************************************************************
+ * fat_getrootdirentry(fatfs,entryidx,entry)
+ *
+ * Read a root directory entry. The FAT12/16 root directory
+ * is a contiguous group of sectors, whose size is specified in
+ * the BPB. This routine just digs out an entry from there
+ *
+ * Input parameters:
+ * fatfs - FAT filesystem descriptor
+ * entryidx - 0-based entry index to read
+ * entry - pointer to directory entry (32 bytes)
+ *
+ * Return value:
+ * 0 if ok
+ * <0 if error occured
+ ********************************************************************* */
+
+static int fat_getrootdirentry(fatfs_t *fatfs,int entryidx,uint8_t *entry)
+{
+ int rootdirstart;
+ int rootdirsize;
+ int dirsecnum;
+ int res;
+
+ if (entryidx >= fatfs->fat_bpb.bpb_maxrootdir) {
+ memset(entry,0,DIRENTRYSIZE);
+ return CFE_ERR_INV_PARAM;
+ }
+
+ rootdirstart = fatfs->fat_bpb.bpb_reservedsectors +
+ fatfs->fat_bpb.bpb_numfats * fatfs->fat_bpb.bpb_sectorsperfat;
+
+ rootdirsize = fatfs->fat_bpb.bpb_maxrootdir / DIRENTRYSIZE;
+
+ dirsecnum = rootdirstart + entryidx / DIRPERSECTOR;
+
+ if (fatfs->fat_dirsecnum != dirsecnum) {
+ res = fat_readsector(fatfs,dirsecnum,1,fatfs->fat_dirsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_dirsecnum = dirsecnum;
+ }
+
+ memcpy(entry,&(fatfs->fat_dirsector[(entryidx % DIRPERSECTOR)*DIRENTRYSIZE]),
+ DIRENTRYSIZE);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_checksumname(name)
+ *
+ * Calculate the "long filename" checksum for a given short name.
+ * All LFN directory entries associated with the short name are
+ * given the same checksum byte, to help keep the long name
+ * consistent.
+ *
+ * Input parameters:
+ * name - pointer to 32-byte directory entry
+ *
+ * Return value:
+ * checksum value
+ ********************************************************************* */
+
+static uint8_t fat_checksumname(uint8_t *name)
+{
+ uint8_t sum = 0;
+ uint8_t newbit;
+ int idx;
+
+ for (idx = 0; idx < 11; idx++) {
+ newbit = (sum & 1) ? 0x80 : 0x00;
+ sum >>= 1;
+ sum |= newbit;
+ sum += name[idx];
+ }
+
+ return sum;
+}
+
+#ifdef _FATFS_DEBUG_
+void fat_dumpdirentry(uint8_t *entry);
+void fat_dumpdirentry(uint8_t *entry)
+{
+ uint8_t name[32];
+ int idx;
+
+ if (entry[11] != ATTRIB_LFN) {
+ memcpy(name,entry,11);
+ name[11] = 0;
+ xprintf("%s %02X %04X %d\n",
+ name,DIRENTRY_ATTRIB(entry),
+ DIRENTRY_STARTCLUSTER(entry),
+ DIRENTRY_FILELENGTH(entry));
+ }
+ else {
+ for (idx = 0; idx < 5; idx++) {
+ name[idx] = entry[(idx*2)+1];
+ }
+ for (idx = 0; idx < 6; idx++) {
+ name[idx+5] = entry[(idx*2)+14];
+ }
+ for (idx = 0; idx < 2; idx++) {
+ name[idx+11] = entry[(idx*2)+28];
+ }
+ name[13] = '\0';
+ xprintf("%02X: %s %04X cksum %02X\n",entry[0],
+ name,READWORD(entry,0x1A),entry[13]);
+ }
+}
+#endif
+
+
+/* *********************************************************************
+ * fat_walkfatchain(fat,start,arg,func)
+ *
+ * Walk a FAT chain, calling a callback routine for each entry
+ * we find along the way.
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * start - starting FAT entry (from the directory, usually)
+ * arg - argument to pass to callback routine
+ * func - function to call for each FAT entry
+ *
+ * Return value:
+ * 0 if all elements processed
+ * <0 if error occured
+ * >0 if callback routine returned a nonzero value
+ ********************************************************************* */
+
+static int fat_walkfatchain(fatfs_t *fat,int start,
+ void *arg,
+ int (*func)(fatfs_t *fat,
+ int e,
+ int prev_e,
+ void *arg))
+{
+ int prev_e = 0;
+ int ending_e;
+ int e;
+ int res = 0;
+
+ e = start;
+
+ /* Note: ending FAT entry can be 0x(F)FF8..0x(F)FFF. We assume that the
+ 'getfatentry' call won't return values above that. */
+ if (fat->fat_twelvebit) {
+ ending_e = 0xFF8;
+ }
+ else {
+ ending_e = 0xFFF8;
+ }
+
+ while (e < ending_e) {
+ res = (*func)(fat,e,prev_e,arg);
+ if (res) break;
+ prev_e = e;
+ e = fat_getfatentry(fat,e);
+ if (e < 0) return e;
+ }
+
+ return res;
+}
+
+/* *********************************************************************
+ * fat_getwalkfunc(fat,e,prev_e,arg)
+ *
+ * Callback routien to collect all of the FAT entries into
+ * a FAT chain descriptor
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * e - current entry
+ * prev_e - previous entry (0 if first entry)
+ * arg - argument passed to fat_walkfatchain
+ *
+ * Return value:
+ * 0 to keep walking
+ * else value to return from fat_walkfatchain
+ ********************************************************************* */
+
+static int fat_getwalkfunc(fatfs_t *fat,int e,
+ int prev_e,void *arg)
+{
+ fatchain_t *chain = arg;
+
+ if (chain->fat_entries) {
+ chain->fat_entries[chain->fat_count] = (uint16_t) e;
+ }
+
+ chain->fat_count++;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_getchain(fat,start,chain)
+ *
+ * Walk an entire FAT chain and remember the chain in a
+ * FAT chain descriptor
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * start - starting FAT entry
+ * chain - chain descriptor
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_getchain(fatfs_t *fat,int start,fatchain_t *chain)
+{
+ int res;
+
+ chain->fat_entries = NULL;
+ chain->fat_count = 0;
+ chain->fat_start = start;
+
+ /*
+ * walk once to count the entries.
+ *
+ * For regular files, you probably don't have to do this
+ * since you can predict exactly how many FAT entries
+ * there are given the file length.
+ */
+
+ res = fat_walkfatchain(fat,start,chain,fat_getwalkfunc);
+ if (res < 0) return res;
+
+ /*
+ * allocate space for the entries. Include one extra
+ * slot for the first entry, since the first entry
+ * does not actually appear in the FAT (the fat is
+ * only the 'next' pointers).
+ */
+
+ if (chain->fat_count == 0) return 0;
+ chain->fat_entries = KMALLOC((chain->fat_count+1)*sizeof(uint16_t),0);
+ chain->fat_count = 0;
+
+ /*
+ * walk again to collect entries
+ */
+ res = fat_walkfatchain(fat,start,chain,fat_getwalkfunc);
+ if (res < 0) return res;
+
+ return chain->fat_count;
+}
+
+
+/* *********************************************************************
+ * fat_freechain(chain)
+ *
+ * Free memory associated with a FAT chain
+ *
+ * Input parameters:
+ * chain - chain descriptor
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void fat_freechain(fatchain_t *chain)
+{
+ if (chain->fat_entries) {
+ KFREE(chain->fat_entries);
+ chain->fat_entries = NULL;
+ }
+ chain->fat_count = 0;
+}
+
+/* *********************************************************************
+ * fat_clusteridx(fat,chain,idx)
+ *
+ * Index into a FAT chain and return the nth cluster number
+ * from the chain
+ *
+ * Input parameters:
+ * fat - fat filesystem descriptor
+ * chain - chain descriptor
+ * idx - index into FAT chain
+ *
+ * Return value:
+ * FAT entry at the nth index, or
+ * <0 if an error occured
+ ********************************************************************* */
+static int fat_clusteridx(fatfs_t *fat,fatchain_t *chain,int idx)
+{
+ if (idx >= chain->fat_count) return CFE_ERR_INV_PARAM; /* error! */
+ return (int) (unsigned int) chain->fat_entries[idx];
+}
+
+/* *********************************************************************
+ * fat_sectoridx(fat,chain,idx)
+ *
+ * Return the sector nunber of the nth sector in a given
+ * FAT chain. This routine knows how to translate cluster
+ * numbers into sector numbers.
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * chain - FAT chain
+ * idx - index of which sector to find
+ *
+ * Return value:
+ * sector number
+ * <0 if an error occured
+ ********************************************************************* */
+static int fat_sectoridx(fatfs_t *fat,fatchain_t *chain,int idx)
+{
+ int clusteridx;
+ int sectoridx;
+ int sector;
+ int fatentry;
+
+ clusteridx = idx / fat->fat_bpb.bpb_sectorspercluster;
+ sectoridx = idx % fat->fat_bpb.bpb_sectorspercluster;
+
+ fatentry = fat_clusteridx(fat,chain,clusteridx);
+
+ if (fatentry < 0) xprintf("ran off end of fat chain!\n");
+ if (fatentry < 2) xprintf("fat entries should be >= 2\n");
+
+ sector = fat->fat_bpb.bpb_reservedsectors +
+ (fat->fat_bpb.bpb_maxrootdir * DIRENTRYSIZE)/SECTORSIZE +
+ (fat->fat_bpb.bpb_numfats * fat->fat_bpb.bpb_sectorsperfat) +
+ (fatentry - 2) * fat->fat_bpb.bpb_sectorspercluster +
+ sectoridx;
+
+ return sector;
+}
+
+/* *********************************************************************
+ * fat_getsubdirentry(fat,chain,idx,direntry)
+ *
+ * This routine is similar to fat_getrootdirentry except it
+ * works on a subdirectory. FAT subdirectories are like files
+ * containing directory entries, so we use the "get nth sector
+ * in chain" routines to walk the chains of sectors reading directory
+ * entries.
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * chain - FAT chain
+ * idx - index of entry to read
+ * direntry - place to put directory entry we read
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_getsubdirentry(fatfs_t *fat,fatchain_t *chain,
+ int idx,uint8_t *direntry)
+{
+ int sector;
+ int res;
+
+ sector = fat_sectoridx(fat,chain,idx/DIRPERSECTOR);
+
+ if (sector < 0) return sector;
+
+ if (fat->fat_dirsecnum != sector) {
+ res = fat_readsector(fat,sector,1,fat->fat_dirsector);
+ if (res < 0) {
+ return res;
+ }
+ fat->fat_dirsecnum = sector;
+ }
+
+ memcpy(direntry,&(fat->fat_dirsector[(idx % DIRPERSECTOR)*DIRENTRYSIZE]),
+ DIRENTRYSIZE);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_getshortname(direntry,name)
+ *
+ * Read the short filename from a directory entry, converting
+ * it into its classic 8.3 form
+ *
+ * Input parameters:
+ * direntry - directory entry
+ * name - place to put 8.3 name
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void fat_getshortname(uint8_t *direntry,char *name)
+{
+ int idx;
+
+ /*
+ * Collect the base file name
+ */
+
+ for (idx = DIR_NAMEOFFSET; idx < (DIR_NAMEOFFSET+DIR_NAMELEN); idx++) {
+ if (direntry[idx] == ' ') break;
+ *name++ = direntry[idx];
+ }
+
+ /*
+ * Put in the dot for the extension only if there
+ * is an extension.
+ */
+
+ if (direntry[DIR_EXTOFFSET] != ' ') *name++ = '.';
+
+ /*
+ * Collect the extension
+ */
+
+ for (idx = DIR_EXTOFFSET; idx < (DIR_EXTOFFSET+DIR_EXTLEN); idx++) {
+ if (direntry[idx] == ' ') break;
+ *name++ = direntry[idx];
+ }
+
+ *name = '\0';
+}
+
+
+/* *********************************************************************
+ * fat_getlongname(fat,chain,diridx,shortentry,longname)
+ *
+ * Look backwards in the directory to locate the long file name
+ * that corresponds to the short file name passed in 'shortentry'
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * chain - chain describing current directory, or NULL
+ * if the current directory is the root directory
+ * diridx - index of the short file name
+ * shortentry - points to the short directory entry
+ * longname - buffer to receive long file name (up to 261 chars)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_getlongname(fatfs_t *fat,fatchain_t *chain,int diridx,
+ uint8_t *shortentry,char *longname)
+{
+ int lfnidx = 1;
+ uint8_t checksum;
+ uint8_t direntry[DIRENTRYSIZE];
+ int idx;
+ char *lfnptr;
+ int badlfn = 0;
+
+ *longname = '\0';
+
+ /*
+ * idx is the entry # of the short name
+ */
+
+ checksum = fat_checksumname(shortentry);
+
+ /*
+ * Start working backwards from current entry
+ * and collect pieces of the lfn
+ */
+
+ lfnptr = longname;
+ diridx--;
+
+ while (diridx > 0) {
+
+ /*
+ * Read previous entry
+ */
+
+ if (chain) {
+ fat_getsubdirentry(fat,chain,diridx,direntry);
+ }
+ else {
+ fat_getrootdirentry(fat,diridx,direntry);
+ }
+
+ /*
+ * Checksum must match, it must have the right entry index,
+ * and it must have the LFN attribute
+ */
+
+ if (DIRENTRY_CHECKSUM(direntry) != checksum) {
+ badlfn = 1;
+ break;
+ }
+ if ((DIRENTRY_LFNIDX(direntry) & LFNIDX_MASK) != lfnidx) {
+ badlfn = 1;
+ break;
+ }
+
+ if (DIRENTRY_ATTRIB(direntry) != ATTRIB_LFN) {
+ badlfn = 1;
+ break;
+ }
+
+ /*
+ * Collect the chars from the filename. Note we
+ * don't deal well with real unicode chars here.
+ */
+
+ for (idx = 0; idx < 5; idx++) {
+ *lfnptr++ = direntry[(idx*2)+1];
+ }
+ for (idx = 0; idx < 6; idx++) {
+ *lfnptr++ = direntry[(idx*2)+14];
+ }
+ for (idx = 0; idx < 2; idx++) {
+ *lfnptr++ = direntry[(idx*2)+28];
+ }
+
+ /*
+ * Don't go too far
+ */
+
+ if (DIRENTRY_LFNIDX(direntry) & LFNIDX_END) break;
+ lfnidx++;
+ if (lfnidx > LFNIDX_MAX) {
+ badlfn = 1;
+ break;
+ }
+
+ diridx--;
+ }
+
+ /*
+ * Null terminate the lfn
+ */
+
+ *lfnptr = 0;
+
+ if (badlfn) {
+ longname[0] = 0;
+ return CFE_ERR_FILENOTFOUND;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fat_scandir(fat,chain,name,direntry)
+ *
+ * Scan a single directory looking for a file name
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * chain - FAT chain for directory or NULL for root directory
+ * name - name of file to look for (short or long name)
+ * direntry - place to put directory entry if we find one
+ *
+ * Return value:
+ * 1 if name was found
+ * 0 if name was not found
+ * else <0 is error code
+ ********************************************************************* */
+
+
+static int fat_scandir(fatfs_t *fat,fatchain_t *chain,
+ char *name,uint8_t *direntry)
+{
+ int idx;
+ int count;
+ char shortname[16];
+ char longname[280];
+
+ /*
+ * Get directory size
+ */
+
+ if (chain) {
+ count = (chain->fat_count * fat->fat_bpb.bpb_sectorspercluster) * DIRPERSECTOR;
+ }
+ else {
+ count = (int) fat->fat_bpb.bpb_maxrootdir;
+ }
+
+ /*
+ * Scan whole directory
+ */
+
+ for (idx = 0; idx < count; idx++) {
+
+ /*
+ * Get entry by root or chain depending...
+ */
+
+ if (chain) {
+ fat_getsubdirentry(fat,chain,idx,direntry);
+ }
+ else {
+ fat_getrootdirentry(fat,idx,direntry);
+ }
+
+ /*
+ * Ignore stuff we don't want to see
+ */
+
+ if (direntry[0] == DIRENTRY_LAST) break; /* stop if at end of dir */
+ if (direntry[0] == DIRENTRY_DELETED) continue; /* skip deleted entries */
+ if (direntry[0] == DIRENTRY_PARENTDIR) continue; /* skip ./.. entries */
+
+ if (DIRENTRY_ATTRIB(direntry) == ATTRIB_LFN) continue; /* skip LFNs */
+ if (DIRENTRY_ATTRIB(direntry) & ATTRIB_LABEL) continue; /* skip volume labels */
+
+ /*
+ * Get actual file names from directory
+ */
+
+ fat_getshortname(direntry,shortname);
+ fat_getlongname(fat,chain,idx,direntry,longname);
+
+
+ if (name) {
+ if (strcmpi(name,shortname) == 0) return 1;
+ if (longname[0] && (strcmpi(name,longname) == 0)) return 1;
+ }
+ else {
+ xprintf("%-30s",longname[0] ? longname : shortname);
+// xprintf(" Clus=%04X",DIRENTRY_STARTCLUSTER(direntry));
+// xprintf(" Attrib=%02X",DIRENTRY_ATTRIB(direntry));
+// xprintf(" Size=%d",DIRENTRY_FILELENGTH(direntry));
+ xprintf("%d",DIRENTRY_FILELENGTH(direntry));
+ xprintf("\n");
+ }
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_findfile(fat,name,direntry)
+ *
+ * Locate a directory entry given a complete path name
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * name - name of file to locate (forward or reverse slashses ok)
+ * direntry - place to put directory entry we find
+ *
+ * Return value:
+ * 0 if file not found
+ * 1 if file was found
+ * <0 if error occurs
+ ********************************************************************* */
+
+static int fat_findfile(fatfs_t *fat,char *name,uint8_t *direntry)
+{
+ char *namecopy;
+ char *namepart;
+ char *ptr;
+ fatchain_t chain;
+ int res;
+ int e;
+
+ /*
+ * Copy the name, we're going to hack it up
+ */
+
+ namecopy = strdup(name);
+
+ /*
+ * Chew off the first piece up to the first slash. Remove
+ * a leading slash if it is there.
+ */
+
+ ptr = namecopy;
+
+ if ((*ptr == '/') || (*ptr == '\\')) ptr++;
+
+ namepart = ptr;
+ while (*ptr && (*ptr != '/') && (*ptr != '\\')) ptr++;
+ if (*ptr) *ptr++ = '\0';
+
+ /*
+ * Scan the root directory looking for the first piece
+ */
+
+ res = fat_scandir(fat,NULL,namepart,direntry);
+ if (res == 0) {
+ KFREE(namecopy);
+ return 0; /* file not found */
+ }
+
+
+ /*
+ * Start scanning subdirectories until we run out
+ * of directory components.
+ */
+
+ namepart = ptr;
+ while (*ptr && (*ptr != '/') && (*ptr != '\\')) ptr++;
+ if (*ptr) *ptr++ = '\0';
+ if (!*namepart) namepart = NULL;
+
+
+ while (namepart) {
+
+ /*
+ * Scan the subdirectory
+ */
+
+ e = DIRENTRY_STARTCLUSTER(direntry);
+ memset(&chain,0,sizeof(chain));
+ fat_getchain(fat,e,&chain);
+ res = fat_scandir(fat,&chain,namepart,direntry);
+ if (res == 0) {
+ break;
+ }
+ fat_freechain(&chain);
+
+ /*
+ * Advance to the next piece
+ */
+
+ namepart = ptr;
+ while (*ptr && (*ptr != '/') && (*ptr != '\\')) ptr++;
+ if (*ptr) *ptr++ = '\0';
+ if (!*namepart) namepart = NULL;
+
+ /*
+ * If there's more to go and we hit something that
+ * is not a directory, stop here.
+ */
+
+ if (namepart && !(DIRENTRY_ATTRIB(direntry) & ATTRIB_DIR)) {
+ res = 0;
+ }
+ }
+
+ KFREE(namecopy);
+
+ /*
+ * The last piece we enumerate has to be a file.
+ */
+
+ if ((res > 0) &&
+ (DIRENTRY_ATTRIB(direntry) & ATTRIB_DIR)) {
+ return 0;
+ }
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * fat_init(fat,name)
+ *
+ * Create the filesystem descriptor and attach to the hardware
+ * device.
+ *
+ * Input parameters:
+ * fat - filesystem descriptor
+ * name - hardware device name
+ * part - true to look for partition tables
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_init(fatfs_t *fat,char *name,int part)
+{
+ int res;
+
+ memset(fat,0,sizeof(fatfs_t));
+ fat->fat_dirsecnum = -1;
+ fat->fat_fatsecnum = -1;
+
+ fat->fat_fh = cfe_open(name);
+
+ if (fat->fat_fh < 0) return fat->fat_fh;
+
+ res = fatfs_check_for_partition_table(fat);
+ /* If we were able to figure it out, use that as the default */
+ if (res >= 0) part = res;
+
+ if (part) {
+ res = fat_findpart(fat);
+ if (res < 0) {
+ cfe_close(fat->fat_fh);
+ fat->fat_fh = -1;
+ return res;
+ }
+ }
+
+ res = fat_readbpb(fat);
+ if (res != 0) {
+ cfe_close(fat->fat_fh);
+ fat->fat_fh = -1;
+ return res;
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_uninit(fat)
+ *
+ * Uninit the filesystem descriptor and release any resources
+ * we allocated.
+ *
+ * Input parameters:
+ * fat - filesystem descriptor
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void fat_uninit(fatfs_t *fat)
+{
+ if (fat->fat_fh >= 0) cfe_close(fat->fat_fh);
+ fat->fat_fh = -1;
+}
+
+int fatfs_fileop_dir(void *fsctx);
+int fatfs_fileop_dir(void *fsctx)
+{
+ fatfs_t *fatfs = fsctx;
+ uint8_t direntry[32];
+
+ fat_scandir(fatfs,NULL,NULL,direntry);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fatfs_fileop_init(fsctx,devname)
+ *
+ * Create a FAT filesystem context and open the associated
+ * block device.
+ *
+ * Input parameters:
+ * fsctx - file system context (return pointer)
+ * devname - device name to open
+ * part - true to look for a partition table
+ *
+ * Return value:
+ * 0 if ok, else error
+ ********************************************************************* */
+
+static int fatfs_fileop_init(void **fsctx,char *devname,int part)
+{
+ int res;
+ fatfs_t *fatfs;
+
+ /*
+ * Allocate a file system context
+ */
+
+ fatfs = (fatfs_t *) KMALLOC(sizeof(fatfs_t),0);
+ if (!fatfs) return CFE_ERR_NOMEM;
+
+ /*
+ * Open a handle to the underlying device
+ */
+
+ res = fat_init(fatfs,devname,part);
+ if (res != 0) {
+ KFREE(fatfs);
+ return res;
+ }
+
+ *fsctx = fatfs;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fatfs_check_for_partition_table(fatfs)
+ *
+ * This routine attempts to determine if the disk contains a
+ * partition table or if it contains a standard MS-DOS boot recod.
+ * We try to find both, and return what we find, or an error
+ * if it is still unclear.
+ *
+ * Input parameters:
+ * fatfs - fat filesystem context
+ *
+ * Return value:
+ * 0 if no partition table
+ * 1 if partition table
+ * <0 = error occured, could not tell or I/O error
+ ********************************************************************* */
+
+static int fatfs_check_for_partition_table(fatfs_t *fatfs)
+{
+ int res;
+ uint8_t buffer[SECTORSIZE];
+ uint8_t *part;
+ int idx;
+ int foundit = 0;
+
+ /*
+ * Read sector 0
+ */
+
+ fatfs->fat_partstart = 0;
+ res = fat_readsector(fatfs,0,1,buffer);
+ if (res < 0) return res;
+
+ /*
+ * Check the seal at the end of th sector. Both
+ * boot sector and MBR should contain this seal.
+ */
+ if (READWORD(buffer,BPB_SEAL) != BPB_SEAL_VALUE) {
+ res = CFE_ERR_BADFILESYS;
+ return res;
+ }
+
+ /*
+ * See Microsoft Knowledgebase article # Q140418, it contains
+ * a good description of the boot sector format.
+ *
+ * If the extended information is present, and SystemID is "FAT"
+ * and the "bytes per sector" is 512, assume it's a regular boot block
+ */
+
+ if (((buffer[BPB_SIGNATURE] == BPB_SIGNATURE_VALUE1) ||
+ (buffer[BPB_SIGNATURE] == BPB_SIGNATURE_VALUE2)) &&
+ (memcmp(&buffer[BPB_SYSTEMID],"FAT",3) == 0) &&
+ (READWORD(buffer,BPB_BYTESPERSECTOR) == 512)) {
+ /* Not partitioned */
+ res = 0;
+ return res;
+ }
+
+ /* If no extended information is present, check a few other key values. */
+
+ if ((READWORD(buffer,BPB_BYTESPERSECTOR) == 512) &&
+ (READWORD(buffer,BPB_RESERVEDSECTORS) >= 1) &&
+ ((READWORD(buffer,BPB_MEDIADESCRIPTOR) & 0xF0) == 0xF0)) {
+ res = 0;
+ return res;
+ }
+
+ /*
+ * If we're still confused, look for a partition table with a valid FAT
+ * partition on it. We might not detect a partition table that has
+ * only non-FAT partitions on it, like a disk with all Linux partitions,
+ * but that is fine here in the FATFS module, since we only want to
+ * find FAT partitions anyway.
+ */
+ part = &buffer[PTABLE_OFFSET];
+ for (idx = 0; idx < PTABLE_COUNT; idx++) {
+
+ if (((part[PTABLE_STATUS] == PTABLE_STATUS_ACTIVE) ||
+ (part[PTABLE_STATUS] == 0x00)) &&
+ ((part[PTABLE_TYPE] == PARTTYPE_FAT12) ||
+ (part[PTABLE_TYPE] == PARTTYPE_FAT16) ||
+ (part[PTABLE_TYPE] == PARTTYPE_FAT16BIG))) {
+ foundit = 1;
+ res = 1; /*Partition table present*/
+ break;
+ }
+ part += PTABLE_SIZE;
+ }
+
+ /*
+ * If at this point we did not find what we were looking for,
+ * return an error.
+ */
+ if (foundit) {
+ res = 1; /*Partition table is present.*/
+ }
+ else {
+ /*Error! We can't decide if partition table exists or not*/
+ res = CFE_ERR_BADFILESYS;
+ }
+
+ return res;
+}
+
+static int fatfs_fileop_xinit(void **fsctx,void *dev)
+{
+ char *devname = (char *) dev;
+
+ return fatfs_fileop_init(fsctx,devname,0);
+}
+
+static int fatfs_fileop_pinit(void **fsctx,void *dev)
+{
+ char *devname = (char *) dev;
+
+ return fatfs_fileop_init(fsctx,devname,1);
+}
+
+
+
+/* *********************************************************************
+ * fatfs_fileop_open(ref,name)
+ *
+ * Open a file on the FAT device.
+ *
+ * Input parameters:
+ * ref - place to store pointer to fileinfo
+ * fsctx - filesystem context
+ * name - name of file to open
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fatfs_fileop_open(void **ref,void *fsctx,char *name,int mode)
+{
+ int res;
+ uint8_t direntry[DIRENTRYSIZE];
+ fatfile_t *ff;
+ fatfs_t *fatfs;
+
+ if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ fatfs = (fatfs_t *) fsctx;
+
+ ff = (fatfile_t *) KMALLOC(sizeof(fatfile_t),0);
+ if (ff == NULL) return CFE_ERR_NOMEM;
+
+ memset(ff,0,sizeof(fatfile_t));
+
+ ff->ff_fat = fatfs;
+
+ res = fat_findfile(ff->ff_fat,name,direntry);
+ if (res <= 0) {
+ return CFE_ERR_FILENOTFOUND; /* not found */
+ }
+
+ /*
+ * Okay, the file was found. Enumerate the FAT chain
+ * associated with this file.
+ */
+
+ ff->ff_filelength = DIRENTRY_FILELENGTH(direntry);
+
+ ff->ff_curpos = 0;
+ ff->ff_cursector = -1;
+
+ res = fat_getchain(ff->ff_fat,
+ DIRENTRY_STARTCLUSTER(direntry),
+ &(ff->ff_chain));
+
+ if (res < 0) {
+ KFREE(ff);
+ return res;
+ }
+
+ /*
+ * Return the file handle
+ */
+
+
+ fatfs->fat_refcnt++;
+ *ref = (void *) ff;
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fatfs_fileop_close(ref)
+ *
+ * Close the file.
+ *
+ * Input parameters:
+ * ref - pointer to open file information
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void fatfs_fileop_close(void *ref)
+{
+ fatfile_t *file = (fatfile_t *) ref;
+ fatfs_t *fatctx = file->ff_fat;
+
+ fatctx->fat_refcnt--;
+
+ fat_freechain(&(file->ff_chain));
+ KFREE(file);
+}
+
+
+/* *********************************************************************
+ * fatfs_fileop_uninit(ref)
+ *
+ * Uninitialize the file system.
+ *
+ * Input parameters:
+ * fsctx - filesystem context
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void fatfs_fileop_uninit(void *fsctx)
+{
+ fatfs_t *fatctx = (fatfs_t *) fsctx;
+
+ if (fatctx->fat_refcnt) {
+ xprintf("fatfs_fileop_unint: warning: refcnt should be zero\n");
+ }
+
+ fat_uninit(fatctx);
+
+ KFREE(fatctx);
+}
+
+
+/* *********************************************************************
+ * fatfs_fileop_seek(ref,offset,how)
+ *
+ * Move the file pointer within the file
+ *
+ * Input parameters:
+ * ref - pointer to open file information
+ * offset - new file location or distance to move
+ * how - method for moving
+ *
+ * Return value:
+ * new file offset
+ * <0 if error occured
+ ********************************************************************* */
+
+static int fatfs_fileop_seek(void *ref,int offset,int how)
+{
+ fatfile_t *file = (fatfile_t *) ref;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ file->ff_curpos = offset;
+ break;
+ case FILE_SEEK_CURRENT:
+ file->ff_curpos += offset;
+ break;
+ default:
+ break;
+ }
+
+ if (file->ff_curpos >= file->ff_filelength) {
+ file->ff_curpos = file->ff_filelength;
+ }
+
+ return file->ff_curpos;
+}
+
+
+/* *********************************************************************
+ * fatfs_fileop_read(ref,buf,len)
+ *
+ * Read data from the file.
+ *
+ * Input parameters:
+ * ref - pointer to open file information
+ * buf - buffer to read data into
+ * len - number of bytes to read
+ *
+ * Return value:
+ * number of bytes read
+ * <0 if error occured
+ * 0 means eof
+ ********************************************************************* */
+
+static int fatfs_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ fatfile_t *file = (fatfile_t *) ref;
+ int amtcopy;
+ int ttlcopy = 0;
+ int offset;
+ int sector;
+ int secidx;
+ int origpos;
+ int res;
+ uint8_t temp_buf[SECTORSIZE];
+
+ /*
+ * Remember orig position in case we have an error
+ */
+
+ origpos = file->ff_curpos;
+
+ /*
+ * bounds check the length based on the file length
+ */
+
+ if ((file->ff_curpos + len) > file->ff_filelength) {
+ len = file->ff_filelength - file->ff_curpos;
+ }
+
+ res = 0;
+
+ /*
+ * while ther is still data to be transferred
+ */
+
+
+ while (len) {
+
+ /*
+ * Calculate the sector offset and index in the sector
+ */
+
+ offset = file->ff_curpos % SECTORSIZE;
+ secidx = file->ff_curpos / SECTORSIZE;
+
+ sector = fat_sectoridx(file->ff_fat,&(file->ff_chain),secidx);
+
+ if (sector < 0) {
+ xprintf("should not happen, sector = -1!\n");
+ return sector;
+ }
+
+ /*
+ * first transfer up to the sector boundary
+ */
+
+ amtcopy = len;
+ if (amtcopy > (SECTORSIZE-offset)) {
+ amtcopy = (SECTORSIZE-offset);
+ }
+
+ /*
+ * If transferring exactly a sector, on a sector
+ * boundary, read the data directly into the user buffer
+ *
+ * Extra credit: See if we can transfer more than one
+ * sector at a time, by determining if we can read a run of
+ * contiguous sectors (very likely)
+ *
+ * Otherwise: read into the sector buffer and
+ * transfer the data to user memory.
+ */
+
+ if ((offset == 0) && (amtcopy == SECTORSIZE)) {
+ res = fat_readsector(file->ff_fat,sector,1,temp_buf);
+ if (res < 0) {
+ xprintf("I/O error!\n");
+ break;
+ }
+ memcpy(buf,temp_buf,amtcopy);
+ }
+ else {
+ if (file->ff_cursector != sector) {
+ res = fat_readsector(file->ff_fat,sector,1,file->ff_sector);
+ if (res < 0) {
+ break;
+ }
+ file->ff_cursector = sector;
+ }
+ memcpy(buf,&(file->ff_sector[offset]),amtcopy);
+ }
+
+ /*
+ * Adjust/update all our pointers.
+ */
+
+ buf += amtcopy;
+ file->ff_curpos += amtcopy;
+ ttlcopy += amtcopy;
+ len -= amtcopy;
+
+ /*
+ * see if we ran off the end of the file. Should not
+ * be necessary.
+ */
+
+ if (file->ff_curpos >= file->ff_filelength) {
+ /* should not be necessary */
+ break;
+ }
+ }
+
+ /*
+ * If an error occured, get out now.
+ */
+
+ if (res < 0) {
+ file->ff_curpos = origpos;
+ return res;
+ }
+
+ return ttlcopy;
+
+}
+
+static int fatfs_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ return CFE_ERR_UNSUPPORTED;
+}
+
+
+#if 0
+
+void main(int argc,char *argv[])
+{
+ fatfs_t fat;
+ int idx;
+ unsigned int e;
+ uint8_t direntry[DIRENTRYSIZE];
+ fatchain_t chain;
+ int res;
+
+
+ fat_init(&fat,"floppy.raw");
+
+
+ if (fat_readbpb(&fat) == 0) {
+ fat_dumpbpb(&fat.fat_bpb);
+ }
+
+#if 0
+ for (idx = 0; idx < (int) fat.fat_bpb.bpb_maxrootdir; idx++) {
+ fat_getrootdirentry(&fat,idx,direntry);
+ if (direntry[0] == 0) break;
+ if (direntry[0] == 0xE5) continue;
+ xprintf("%3d: ",idx);
+ fat_dumpdirentry(direntry);
+ }
+#endif
+
+ fat_scandir(&fat,NULL,NULL,direntry);
+
+ for (e = 0x150; e < 0x160; e++) {
+ xprintf("Entry %03X is %03X\n",e,fat_getfatentry(&fat,e));
+ }
+
+#if 0
+ e = 0x36E;
+ while (e != 0xFFF) {
+ e = fat_getfatentry(&fat,e);
+ xprintf("%03X ",e);
+ }
+#endif
+
+
+ xprintf("\n\n");
+ e = 0x36E;
+ memset(&chain,0,sizeof(chain));
+ fat_getchain(&fat,e,&chain);
+ fat_scandir(&fat,&chain,NULL,direntry);
+ fat_freechain(&chain);
+
+ xprintf("\n\n");
+ e = 0x36F;
+ memset(&chain,0,sizeof(chain));
+ fat_getchain(&fat,e,&chain);
+ fat_scandir(&fat,&chain,NULL,direntry);
+ fat_freechain(&chain);
+
+ xprintf("\n\n");
+ e = 0x370;
+ memset(&chain,0,sizeof(chain));
+ fat_getchain(&fat,e,&chain);
+ fat_scandir(&fat,&chain,NULL,direntry);
+ fat_freechain(&chain);
+
+ xprintf("\n\n");
+
+ res = fat_findfile(&fat,argc > 1 ? argv[1] : "/usr/local/include/ansidecl.h",direntry);
+ xprintf("res = %d\n",res);
+
+ if (res) fat_dumpdirentry(direntry);
+
+ close(fat.fat_fh);
+}
+
+void main(int argc,char *argv[])
+{
+ void *ref;
+ int res;
+ char buffer[257];
+ int total = 0;
+
+// res = fatfs_fileop_open(&ref,"floppy.raw:/usr/local/include/bfdlink.h");
+ res = fatfs_fileop_open(&ref,"floppy.raw:/idedrv.h");
+
+ if (res != 0) {
+ xprintf("Could not open file: %d\n",res);
+ exit(1);
+ }
+
+ for (;;) {
+ res = fatfs_fileop_read(ref,buffer,39);
+// xprintf("read returned %d\n",res);
+ if (res <= 0) break;
+
+ if (res > 0) {
+ total += res;
+ buffer[res] = 0;
+ xprintf("%s",buffer);
+ }
+ }
+
+ if (res < 0) xprintf("error! \n");
+
+ xprintf("[total %d]\n",total);
+
+ fatfs_fileop_close(ref);
+
+ exit(0);
+
+}
+
+#endif
diff --git a/cfe/cfe/main/cfe_filesys.c b/cfe/cfe/main/cfe_filesys.c
new file mode 100755
index 0000000..569d7bc
--- /dev/null
+++ b/cfe/cfe/main/cfe_filesys.c
@@ -0,0 +1,343 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Filesystem manager File: cfe_filesys.c
+ *
+ * This module maintains the list of available file systems.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_malloc.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern const fileio_dispatch_t raw_fileops;
+#if CFG_NETWORK
+extern const fileio_dispatch_t tftp_fileops;
+#if (CFG_TCP) && (CFG_HTTPFS)
+extern const fileio_dispatch_t http_fileops;
+#endif
+#endif
+#if CFG_FATFS
+extern const fileio_dispatch_t fatfs_fileops;
+extern const fileio_dispatch_t pfatfs_fileops;
+#endif
+#if CFG_ZLIB
+extern const fileio_dispatch_t zlibfs_fileops;
+#endif
+
+/* *********************************************************************
+ * File system list
+ ********************************************************************* */
+
+static const fileio_dispatch_t * const cfe_filesystems[] = {
+#if !defined(CONFIG_MIPS_BRCM)
+ &raw_fileops,
+#endif
+#if CFG_NETWORK
+ &tftp_fileops,
+#if (CFG_TCP) & (CFG_HTTPFS)
+ &http_fileops,
+#endif
+#endif
+#if CFG_FATFS
+ &fatfs_fileops,
+ &pfatfs_fileops,
+#endif
+#if CFG_ZLIB
+ &zlibfs_fileops,
+#endif
+ NULL
+};
+
+/* *********************************************************************
+ * cfe_findfilesys(name)
+ *
+ * Locate the dispatch record for a particular file system.
+ *
+ * Input parameters:
+ * name - name of filesys to locate
+ *
+ * Return value:
+ * pointer to dispatch table or NULL if not found
+ ********************************************************************* */
+
+const fileio_dispatch_t *cfe_findfilesys(const char *name)
+{
+ const fileio_dispatch_t * const *disp;
+
+ disp = cfe_filesystems;
+
+ while (*disp) {
+ if (strcmp((*disp)->method,name) == 0) return *disp;
+ disp++;
+ }
+
+ return NULL;
+}
+
+/* *********************************************************************
+ * fs_init(name,fsctx,device)
+ *
+ * Initialize a filesystem context
+ *
+ * Input parameters:
+ * name - name of file system
+ * fsctx - returns a filesystem context
+ * device - device name or other info
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+int fs_init(char *fsname,fileio_ctx_t **fsctx,void *device)
+{
+ fileio_ctx_t *ctx;
+ int res;
+ const fileio_dispatch_t *ops;
+
+ ops = cfe_findfilesys((const char *)fsname);
+ if (!ops) return CFE_ERR_FSNOTAVAIL;
+
+ ctx = (fileio_ctx_t *) KMALLOC(sizeof(fileio_ctx_t),0);
+ if (!ctx) return CFE_ERR_NOMEM;
+
+ ctx->ops = ops;
+ res = BDINIT(ops,&(ctx->fsctx),device);
+
+ if (res != 0) {
+ KFREE(ctx);
+ }
+
+ *fsctx = ctx;
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * fs_hook(fsctx,name)
+ *
+ * "Hook" a filesystem to attach a filter, like a decompression
+ * or decryption engine.
+ *
+ * Input parameters:
+ * fsctx - result from a previous fs_init
+ * name - name of fs to hook onto the beginning
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+int fs_hook(fileio_ctx_t *fsctx,char *fsname)
+{
+ void *hookfsctx;
+ const fileio_dispatch_t *ops;
+ int res;
+
+ /*
+ * Find the hook filesystem (well, actually a filter)
+ */
+
+ ops = cfe_findfilesys((const char *)fsname);
+ if (!ops) return CFE_ERR_FSNOTAVAIL;
+
+ /*
+ * initialize our hook file filter.
+ */
+
+ res = BDINIT(ops,&hookfsctx,fsctx);
+ if (res != 0) return res;
+
+ /*
+ * Now replace dispatch table for current filesystem
+ * with the hook's dispatch table. When fs_read is called,
+ * we'll go to the hook, and the hook will call the original.
+ *
+ * When fs_uninit is called, the hook will call the original's
+ * uninit routine.
+ */
+
+ fsctx->ops = ops;
+ fsctx->fsctx = hookfsctx;
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * fs_uninit(fsctx)
+ *
+ * Uninitialize a file system context.
+ *
+ * Input parameters:
+ * fsctx - filesystem context to remove (from fs_init)
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+int fs_uninit(fileio_ctx_t *fsctx)
+{
+ BDUNINIT(fsctx->ops,fsctx->fsctx);
+
+ KFREE(fsctx);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fs_open(fsctx,ref,filename,mode)
+ *
+ * Open a file on the file system
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - returns file handle
+ * filename - name of file to open
+ * mode - file open mode
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+int fs_open(fileio_ctx_t *fsctx,void **ref,char *filename,int mode)
+{
+ return BDOPEN2(fsctx->ops,ref,fsctx->fsctx,filename,mode);
+}
+
+/* *********************************************************************
+ * fs_close(fsctx,ref)
+ *
+ * Close a file on the file system
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - file handle (from fs_open)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+int fs_close(fileio_ctx_t *fsctx,void *ref)
+{
+ BDCLOSE(fsctx->ops,ref);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fs_read(fsctx,ref,buffer,len)
+ *
+ * Read data from the device.
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - file handle (from fs_open)
+ * buffer - buffer pointer
+ * len - length
+ *
+ * Return value:
+ * number of bytes read
+ * 0=eof
+ * <0 = error
+ ********************************************************************* */
+
+int fs_read(fileio_ctx_t *fsctx,void *ref,uint8_t *buffer,int len)
+{
+ return BDREAD(fsctx->ops,ref,buffer,len);
+}
+
+/* *********************************************************************
+ * fs_write(fsctx,ref,buffer,len)
+ *
+ * write data from the device.
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - file handle (from fs_open)
+ * buffer - buffer pointer
+ * len - length
+ *
+ * Return value:
+ * number of bytes written
+ * 0=eof
+ * <0 = error
+ ********************************************************************* */
+
+int fs_write(fileio_ctx_t *fsctx,void *ref,uint8_t *buffer,int len)
+{
+ return BDWRITE(fsctx->ops,ref,buffer,len);
+}
+
+/* *********************************************************************
+ * fs_seek(fsctx,ref,offset,how)
+ *
+ * move file pointer on the device
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - file handle (from fs_open)
+ * offset - distance to move
+ * how - origin (FILE_SEEK_xxx)
+ *
+ * Return value:
+ * new offset
+ * <0 = error
+ ********************************************************************* */
+
+int fs_seek(fileio_ctx_t *fsctx,void *ref,int offset,int how)
+{
+ return BDSEEK(fsctx->ops,ref,offset,how);
+}
diff --git a/cfe/cfe/main/cfe_httpfs.c b/cfe/cfe/main/cfe_httpfs.c
new file mode 100644
index 0000000..4ebad4c
--- /dev/null
+++ b/cfe/cfe/main/cfe_httpfs.c
@@ -0,0 +1,396 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * "HTTP" file system File: cfe_httpfs.c
+ *
+ * This filesystem driver lets you read files from an HTTP
+ * server.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_console.h"
+
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+#if (CFG_TCP) && (CFG_HTTPFS)
+
+#include "net_ebuf.h"
+#include "net_api.h"
+
+
+/* *********************************************************************
+ * HTTP context
+ ********************************************************************* */
+
+/*
+ * File system context - describes overall file system info,
+ * such as the handle to the underlying device.
+ */
+
+typedef struct http_fsctx_s {
+ int http_tmp; /* context not really needed */
+} http_fsctx_t;
+
+/*
+ * File context - describes an open file on the file system.
+ */
+
+#define HTTP_BUFSIZE 1024
+typedef struct http_file_s {
+ http_fsctx_t *http_fsctx;
+ int http_socket;
+ uint8_t http_buffer[HTTP_BUFSIZE];
+ uint8_t *http_bptr;
+ int http_blen;
+ int http_offset;
+ char *http_filename;
+} http_file_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int http_fileop_init(void **fsctx,void *devicename);
+static int http_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int http_fileop_read(void *ref,uint8_t *buf,int len);
+static int http_fileop_write(void *ref,uint8_t *buf,int len);
+static int http_fileop_seek(void *ref,int offset,int how);
+static void http_fileop_close(void *ref);
+static void http_fileop_uninit(void *fsctx);
+
+/* *********************************************************************
+ * RAW fileio dispatch table
+ ********************************************************************* */
+
+const fileio_dispatch_t http_fileops = {
+ "http",
+ FSYS_TYPE_NETWORK,
+ http_fileop_init,
+ http_fileop_open,
+ http_fileop_read,
+ http_fileop_write,
+ http_fileop_seek,
+ http_fileop_close,
+ http_fileop_uninit
+};
+
+static int http_fileop_init(void **newfsctx,void *dev)
+{
+ http_fsctx_t *fsctx;
+
+ *newfsctx = NULL;
+
+ fsctx = KMALLOC(sizeof(http_fsctx_t),0);
+ if (!fsctx) {
+ return CFE_ERR_NOMEM;
+ }
+
+ fsctx->http_tmp = 0;
+ *newfsctx = fsctx;
+
+ return 0;
+}
+
+static int http_fileop_open(void **ref,void *fsctx_arg,char *filename,int mode)
+{
+ http_fsctx_t *fsctx;
+ http_file_t *file;
+ char temp[200];
+ char *hostname, *filen;
+ int hlen;
+ int termidx;
+ int res;
+ int err = 0;
+ char *hptr;
+ char *tok;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ uint8_t termstr[4];
+ uint8_t b;
+
+ if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ fsctx = (http_fsctx_t *) fsctx_arg;
+
+ file = KMALLOC(sizeof(http_file_t),0);
+ if (!file) {
+ return CFE_ERR_NOMEM;
+ }
+
+ file->http_filename = lib_strdup(filename);
+ if (!file->http_filename) {
+ KFREE(file);
+ return CFE_ERR_NOMEM;
+ }
+
+ lib_chop_filename(file->http_filename,&hostname,&filen);
+
+ /*
+ * Look up remote host
+ */
+
+ res = dns_lookup(hostname,hostaddr);
+ if (res < 0) {
+ KFREE(file);
+ return res;
+ }
+
+ file->http_socket = tcp_socket();
+ if (file->http_socket < 0) {
+ KFREE(file->http_filename);
+ KFREE(file);
+ return -1;
+ }
+
+ /*
+ * Connect to remote host.
+ */
+
+ tcp_setflags(file->http_socket,0); /* set socket to blocking */
+ res = tcp_connect(file->http_socket,hostaddr,80);
+
+ if (res < 0) {
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+ return res;
+ }
+
+ /*
+ * Send GET command. Supply the hostname (for HTTP 1.1 requirements)
+ * and set the connection to close as soon as all the data is received.
+ */
+
+ hlen = sprintf(temp,"GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",filen,hostname);
+
+ res = tcp_send(file->http_socket,temp,hlen);
+ if (res < 0) {
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+ return res;
+ }
+
+ /*
+ * Read bytes until we either reach EOF or we see "\r\n\r\n"
+ * This is the server's status string.
+ */
+
+ termstr[0] = '\r'; termstr[1] = '\n';
+ termstr[2] = '\r'; termstr[3] = '\n';
+ termidx = 0;
+
+ file->http_offset = 0;
+ file->http_blen = 0;
+ file->http_bptr = file->http_buffer;
+
+ res = 0;
+ for (;;) {
+ res = tcp_recv(file->http_socket,&b,1);
+ if (res < 0) break;
+ if (b == termstr[termidx]) {
+ termidx++;
+ if (termidx == 4) break;
+ }
+ else {
+ termidx = 0;
+ }
+
+ /*
+ * Save the bytes from the header up to our buffer
+ * size. It's okay if we don't save it all,
+ * since all we want is the result code which comes
+ * first.
+ */
+
+ if (file->http_blen < (HTTP_BUFSIZE-1)) {
+ *(file->http_bptr) = b;
+ file->http_bptr++;
+ file->http_blen++;
+ }
+ }
+
+ /*
+ * Premature EOFs are not good, bail now.
+ */
+
+ if (res < 0) {
+ err = CFE_ERR_EOF;
+ goto protocolerr;
+ }
+
+ /*
+ * Skip past the HTTP response header and grab the result code.
+ * Sanity check it a little.
+ */
+
+ *(file->http_bptr) = 0;
+
+ hptr = file->http_buffer;
+ tok = lib_gettoken(&hptr);
+ if (!tok || (memcmp(tok,"HTTP",4) != 0)) {
+ err = CFE_ERR_PROTOCOLERR;
+ goto protocolerr;
+ }
+
+ tok = lib_gettoken(&hptr);
+ if (!tok) {
+ err = CFE_ERR_PROTOCOLERR;
+ goto protocolerr;
+ }
+
+ switch (lib_atoi(tok)) {
+ case 200:
+ err = 0;
+ break;
+ case 404:
+ err = CFE_ERR_FILENOTFOUND;
+ break;
+
+ }
+
+ /*
+ * If we get to here, the file is okay and we're about to receive data.
+ */
+
+ if (err == 0) {
+ *ref = file;
+ return 0;
+ }
+
+protocolerr:
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+ *ref = NULL;
+ return err;
+}
+
+static int http_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ http_file_t *file = (http_file_t *) ref;
+ int res;
+
+ res = tcp_recv(file->http_socket,buf,len);
+
+ if (res > 0) {
+ file->http_offset += res;
+ return res;
+ }
+
+ return 0; /* Any error becomes "EOF" */
+}
+
+static int http_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ return CFE_ERR_UNSUPPORTED;
+}
+
+static int http_fileop_seek(void *ref,int offset,int how)
+{
+ http_file_t *file = (http_file_t *) ref;
+ int newoffset;
+ int res;
+ int buflen;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ newoffset = offset;
+ break;
+ case FILE_SEEK_CURRENT:
+ newoffset = file->http_offset + offset;
+ break;
+ default:
+ newoffset = offset;
+ break;
+ }
+
+ /*
+ * Can't seek backwards.
+ */
+ if (newoffset < file->http_offset) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ /*
+ * Eat data till offset reaches where we want.
+ */
+
+ while (file->http_offset != newoffset) {
+ buflen = HTTP_BUFSIZE;
+ if (buflen > (newoffset - file->http_offset)) buflen = (newoffset-file->http_offset);
+ res = tcp_recv(file->http_socket,file->http_buffer,buflen);
+ if (res < 0) break;
+ file->http_offset += res;
+ }
+
+ return file->http_offset;
+}
+
+
+static void http_fileop_close(void *ref)
+{
+ http_file_t *file = (http_file_t *) ref;
+
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+}
+
+static void http_fileop_uninit(void *fsctx_arg)
+{
+ http_fsctx_t *fsctx = (http_fsctx_t *) fsctx_arg;
+
+ KFREE(fsctx);
+}
+
+#endif
diff --git a/cfe/cfe/main/cfe_iocb_dispatch.c b/cfe/cfe/main/cfe_iocb_dispatch.c
new file mode 100755
index 0000000..24aea0a
--- /dev/null
+++ b/cfe/cfe/main/cfe_iocb_dispatch.c
@@ -0,0 +1,647 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB dispatcher File: cfe_iocb_dispatch.c
+ *
+ * This routine is the main API dispatch for CFE. User API
+ * calls, via the ROM entry point, get dispatched to routines
+ * in this module.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_error.h"
+#include "cfe_device.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+#include "cfe_fileops.h"
+#include "cfe_boot.h"
+#include "env_subr.h"
+#include "cfe.h"
+#include "cfe_console.h"
+#include "bsp_config.h"
+#include "initdata.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define HV 1 /* handle valid */
+
+#ifndef CFG_BOARD_ID
+#define CFG_BOARD_ID 0
+#endif
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+cfe_devctx_t *cfe_handle_table[CFE_MAX_HANDLE];
+
+extern void _cfe_flushcache(int);
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int cfe_iocb_dispatch(cfe_iocb_t *iocb);
+void cfe_device_poll(void *);
+
+#if CFG_MULTI_CPUS
+extern int altcpu_cmd_start(uint64_t,uint64_t *);
+extern int altcpu_cmd_stop(uint64_t);
+#endif
+
+/* *********************************************************************
+ * Dispatch table
+ ********************************************************************* */
+
+struct cfe_cmd_dispatch_s {
+ int plistsize;
+ int flags;
+ int (*func)(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+};
+
+
+static int cfe_cmd_fw_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_restart(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_boot(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_cpuctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_gettime(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_memenum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_flushcache(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+
+static int cfe_cmd_dev_gethandle(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_open(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_inpstat(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_read(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_write(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_ioctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_close(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+
+static int cfe_cmd_env_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_env_get(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_env_set(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_env_del(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+
+const static struct cfe_cmd_dispatch_s cfe_cmd_dispatch_table[CFE_CMD_MAX] = {
+ {sizeof(iocb_fwinfo_t), 0, cfe_cmd_fw_getinfo}, /* 0 : CFE_CMD_FW_GETINFO */
+ {sizeof(iocb_exitstat_t),0, cfe_cmd_fw_restart}, /* 1 : CFE_CMD_FW_RESTART */
+ {sizeof(iocb_buffer_t), 0, cfe_cmd_fw_boot}, /* 2 : CFE_CMD_FW_BOOT */
+ {sizeof(iocb_cpuctl_t), 0, cfe_cmd_fw_cpuctl}, /* 3 : CFE_CMD_FW_CPUCTL */
+ {sizeof(iocb_time_t), 0, cfe_cmd_fw_gettime}, /* 4 : CFE_CMD_FW_GETTIME */
+ {sizeof(iocb_meminfo_t),0, cfe_cmd_fw_memenum}, /* 5 : CFE_CMD_FW_MEMENUM */
+ {0, 0, cfe_cmd_fw_flushcache}, /* 6 : CFE_CMD_FW_FLUSHCACHE */
+ {-1, 0, NULL}, /* 7 : */
+ {-1, 0, NULL}, /* 8 : */
+ {0, 0, cfe_cmd_dev_gethandle}, /* 9 : CFE_CMD_DEV_GETHANDLE */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_dev_enum}, /* 10 : CFE_CMD_DEV_ENUM */
+ {sizeof(iocb_buffer_t), 0, cfe_cmd_dev_open}, /* 11 : CFE_CMD_DEV_OPEN */
+ {sizeof(iocb_inpstat_t),HV, cfe_cmd_dev_inpstat}, /* 12 : CFE_CMD_DEV_INPSTAT */
+ {sizeof(iocb_buffer_t), HV, cfe_cmd_dev_read}, /* 13 : CFE_CMD_DEV_READ */
+ {sizeof(iocb_buffer_t), HV, cfe_cmd_dev_write}, /* 14 : CFE_CMD_DEV_WRITE */
+ {sizeof(iocb_buffer_t), HV, cfe_cmd_dev_ioctl}, /* 15 : CFE_CMD_DEV_IOCTL */
+ {0, HV, cfe_cmd_dev_close}, /* 16 : CFE_CMD_DEV_CLOSE */
+ {sizeof(iocb_buffer_t), 0, cfe_cmd_dev_getinfo}, /* 17 : CFE_CMD_DEV_GETINFO */
+ {-1, 0, NULL}, /* 18 : */
+ {-1, 0, NULL}, /* 19 : */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_enum}, /* 20 : CFE_CMD_ENV_ENUM */
+ {-1, 0, NULL}, /* 21 : */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_get}, /* 22 : CFE_CMD_ENV_GET */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_set}, /* 23 : CFE_CMD_ENV_SET */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_del}, /* 24 : CFE_CMD_ENV_DEL */
+ {-1, 0, NULL}, /* 25 : */
+ {-1, 0, NULL}, /* 26 : */
+ {-1, 0, NULL}, /* 27 : */
+ {-1, 0, NULL}, /* 28 : */
+ {-1, 0, NULL}, /* 29 : */
+ {-1, 0, NULL}, /* 30 : */
+ {-1, 0, NULL} /* 31 : */
+};
+
+/* *********************************************************************
+ * IOCB dispatch routines
+ ********************************************************************* */
+
+void cfe_device_poll(void *x)
+{
+ int idx;
+ cfe_devctx_t **ctx = cfe_handle_table;
+
+ for (idx = 0; idx < CFE_MAX_HANDLE; idx++,ctx++) {
+ if ((*ctx) && ((*ctx)->dev_dev->dev_dispatch->dev_poll)) {
+ (*ctx)->dev_dev->dev_dispatch->dev_poll(*ctx,cfe_ticks);
+ }
+ }
+}
+
+int cfe_iocb_dispatch(cfe_iocb_t *iocb)
+{
+ const struct cfe_cmd_dispatch_s *disp;
+ int res;
+ cfe_devctx_t *ctx;
+
+ /*
+ * Check for commands codes out of range
+ */
+
+ if ((iocb->iocb_fcode < 0) || (iocb->iocb_fcode >= CFE_CMD_MAX)) {
+ iocb->iocb_status = CFE_ERR_INV_COMMAND;
+ return iocb->iocb_status;
+ }
+
+ /*
+ * Check for command codes in range but invalid
+ */
+
+ disp = &cfe_cmd_dispatch_table[iocb->iocb_fcode];
+
+ if (disp->plistsize < 0) {
+ iocb->iocb_status = CFE_ERR_INV_COMMAND;
+ return iocb->iocb_status;
+ }
+
+ /*
+ * Check for invalid parameter list size
+ */
+
+ if (disp->plistsize != iocb->iocb_psize) {
+ iocb->iocb_status = CFE_ERR_INV_PARAM;
+ return iocb->iocb_status;
+ }
+
+ /*
+ * Determine handle
+ */
+
+ ctx = NULL;
+ if (disp->flags & HV) {
+ if ((iocb->iocb_handle >= CFE_MAX_HANDLE) ||
+ (iocb->iocb_handle < 0) ||
+ (cfe_handle_table[iocb->iocb_handle] == NULL)){
+ iocb->iocb_status = CFE_ERR_INV_PARAM;
+ return iocb->iocb_status;
+ }
+ ctx = cfe_handle_table[iocb->iocb_handle];
+ }
+
+ /*
+ * Dispatch to handler routine
+ */
+
+ res = (*disp->func)(ctx,iocb);
+
+ iocb->iocb_status = res;
+ return res;
+}
+
+static int cfe_newhandle(void)
+{
+ int idx;
+
+ for (idx = 0; idx < CFE_MAX_HANDLE; idx++) {
+ if (cfe_handle_table[idx] == NULL) break;
+ }
+
+ if (idx == CFE_MAX_HANDLE) return -1;
+
+ return idx;
+}
+
+
+/* *********************************************************************
+ * Implementation routines for each IOCB function
+ ********************************************************************* */
+
+static int cfe_cmd_fw_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ iocb_fwinfo_t *info = &iocb->plist.iocb_fwinfo;
+
+ info->fwi_version = (CFE_VER_MAJOR << 16) |
+ (CFE_VER_MINOR << 8) |
+ (CFE_VER_BUILD);
+ info->fwi_totalmem = ((cfe_int64_t) mem_totalsize) << 20;
+ info->fwi_flags =
+#ifdef __long64
+ CFE_FWI_64BIT |
+#else
+ CFE_FWI_32BIT |
+#endif
+#if (CFG_EMBEDDED_PIC)
+ CFE_FWI_RELOC |
+#endif
+#if (!CFG_RUNFROMKSEG0)
+ CFE_FWI_UNCACHED |
+#endif
+#if CFG_MULTI_CPUS
+ CFE_FWI_MULTICPU |
+#endif
+#ifdef _VERILOG_
+ CFE_FWI_RTLSIM |
+#endif
+#ifdef _FUNCSIM_
+ CFE_FWI_FUNCSIM |
+#endif
+ 0;
+
+ info->fwi_boardid = CFG_BOARD_ID;
+ info->fwi_bootarea_pa = (cfe_int64_t) mem_bootarea_start;
+ info->fwi_bootarea_va = BOOT_START_ADDRESS;
+ info->fwi_bootarea_size = (cfe_int64_t) mem_bootarea_size;
+ info->fwi_reserved1 = 0;
+ info->fwi_reserved2 = 0;
+ info->fwi_reserved3 = 0;
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_fw_restart(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ if (iocb->iocb_flags & CFE_FLG_WARMSTART) {
+ cfe_warmstart(iocb->plist.iocb_exitstat.status);
+ }
+ else {
+ cfe_restart();
+ }
+
+ /* should not get here */
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_fw_boot(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ return CFE_ERR_INV_COMMAND; /* not implemented yet */
+}
+
+static int cfe_cmd_fw_cpuctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+#if CFG_MULTI_CPUS
+ int res;
+ uint64_t startargs[4];
+
+ switch (iocb->plist.iocb_cpuctl.cpu_command) {
+ case CFE_CPU_CMD_START:
+
+ startargs[0] = iocb->plist.iocb_cpuctl.start_addr;
+ startargs[1] = iocb->plist.iocb_cpuctl.sp_val;
+ startargs[2] = iocb->plist.iocb_cpuctl.gp_val;
+ startargs[3] = iocb->plist.iocb_cpuctl.a1_val;
+
+ res = altcpu_cmd_start(iocb->plist.iocb_cpuctl.cpu_number,
+ startargs);
+ break;
+ case CFE_CPU_CMD_STOP:
+ res = altcpu_cmd_stop(iocb->plist.iocb_cpuctl.cpu_number);
+ break;
+ default:
+ res = CFE_ERR_INV_PARAM;
+ }
+
+ return res;
+#else
+ return CFE_ERR_INV_COMMAND;
+#endif
+}
+
+static int cfe_cmd_fw_gettime(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ POLL();
+
+ iocb->plist.iocb_time.ticks = cfe_ticks;
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_fw_memenum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int type;
+ int res;
+ uint64_t addr,size;
+
+ res = cfe_arena_enum(iocb->plist.iocb_meminfo.mi_idx,
+ &type,
+ &addr,
+ &size,
+ (iocb->iocb_flags & CFE_FLG_FULL_ARENA) ? TRUE : FALSE);
+
+ iocb->plist.iocb_meminfo.mi_addr = addr;
+ iocb->plist.iocb_meminfo.mi_size = size;
+ iocb->plist.iocb_meminfo.mi_type = type;
+
+ if (res == 0) {
+ if (type == MEMTYPE_DRAM_AVAILABLE) {
+ iocb->plist.iocb_meminfo.mi_type = CFE_MI_AVAILABLE;
+ }
+ else {
+ iocb->plist.iocb_meminfo.mi_type = CFE_MI_RESERVED;
+ }
+ }
+
+ return res;
+}
+
+static int cfe_cmd_fw_flushcache(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ _cfe_flushcache(iocb->iocb_flags);
+ return CFE_OK;
+}
+
+static int cfe_cmd_dev_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ return CFE_ERR_INV_COMMAND;
+}
+
+static int cfe_cmd_dev_gethandle(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ switch (iocb->iocb_flags) {
+ case CFE_STDHANDLE_CONSOLE:
+ if (console_handle == -1) return CFE_ERR_DEVNOTFOUND;
+ iocb->iocb_handle = console_handle;
+ return CFE_OK;
+ break;
+ default:
+ return CFE_ERR_INV_PARAM;
+ }
+}
+
+static int cfe_cmd_dev_open(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int h;
+ cfe_device_t *dev;
+ char devname[64];
+ int res;
+
+ /*
+ * Get device name
+ */
+
+ xstrncpy(devname,(char*)iocb->plist.iocb_buffer.buf_ptr,sizeof(devname));
+
+ /*
+ * Find device in device table
+ */
+
+ dev = cfe_finddev(devname);
+ if (!dev) return CFE_ERR_DEVNOTFOUND;
+
+ /*
+ * Fail if someone else already has the device open
+ */
+
+ if (dev->dev_opencount > 0) return CFE_ERR_DEVOPEN;
+
+ /*
+ * Generate a new handle
+ */
+
+ h = cfe_newhandle();
+ if (h < 0) return CFE_ERR_NOMEM;
+
+ /*
+ * Allocate a context
+ */
+
+ ctx = (cfe_devctx_t *) KMALLOC(sizeof(cfe_devctx_t),0);
+ if (ctx == NULL) return CFE_ERR_NOMEM;
+
+ /*
+ * Fill in the context
+ */
+
+ ctx->dev_dev = dev;
+ ctx->dev_softc = dev->dev_softc;
+ ctx->dev_openinfo = NULL;
+
+ /*
+ * Call driver's open func
+ */
+
+ res = dev->dev_dispatch->dev_open(ctx);
+
+ if (res != 0) {
+ KFREE(ctx);
+ return res;
+ }
+
+ /*
+ * Increment refcnt and save handle
+ */
+
+ dev->dev_opencount++;
+ cfe_handle_table[h] = ctx;
+ iocb->iocb_handle = h;
+
+ /*
+ * Success!
+ */
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_dev_inpstat(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int status;
+
+ status = ctx->dev_dev->dev_dispatch->dev_inpstat(ctx,&(iocb->plist.iocb_inpstat));
+
+ return status;
+}
+
+static int cfe_cmd_dev_read(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int status;
+
+ status = ctx->dev_dev->dev_dispatch->dev_read(ctx,&(iocb->plist.iocb_buffer));
+
+ return status;
+}
+
+static int cfe_cmd_dev_write(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int status;
+
+ status = ctx->dev_dev->dev_dispatch->dev_write(ctx,&(iocb->plist.iocb_buffer));
+
+ return status;
+}
+
+static int cfe_cmd_dev_ioctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int status;
+
+ status = ctx->dev_dev->dev_dispatch->dev_ioctl(ctx,&(iocb->plist.iocb_buffer));
+
+ return status;
+}
+
+static int cfe_cmd_dev_close(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ /*
+ * Call device close function
+ */
+
+ ctx->dev_dev->dev_dispatch->dev_close(ctx);
+
+ /*
+ * Decrement refcnt
+ */
+
+ ctx->dev_dev->dev_opencount--;
+
+ /*
+ * Wipe out handle
+ */
+
+ cfe_handle_table[iocb->iocb_handle] = NULL;
+
+ /*
+ * Release device context
+ */
+
+ KFREE(ctx);
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_dev_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ cfe_device_t *dev;
+ char devname[64];
+ char *x;
+
+ /*
+ * Get device name
+ */
+
+ xstrncpy(devname,(char*)iocb->plist.iocb_buffer.buf_ptr,sizeof(devname));
+
+ /*
+ * Find device in device table
+ */
+
+ if ((x = strchr(devname,':'))) *x = '\0';
+ dev = cfe_finddev(devname);
+ if (!dev) return CFE_ERR_DEVNOTFOUND;
+
+ /*
+ * Return device class
+ */
+
+ iocb->plist.iocb_buffer.buf_devflags = dev->dev_class;
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_env_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int vallen,namelen,res;
+
+ namelen = iocb->plist.iocb_envbuf.name_length;
+ vallen = iocb->plist.iocb_envbuf.val_length;
+
+ res = env_enum(iocb->plist.iocb_envbuf.enum_idx,
+ (char*)iocb->plist.iocb_envbuf.name_ptr,
+ &namelen,
+ (char*)iocb->plist.iocb_envbuf.val_ptr,
+ &vallen);
+
+ if (res < 0) return CFE_ERR_ENVNOTFOUND;
+
+ return CFE_OK;
+}
+
+
+static int cfe_cmd_env_get(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ char *env;
+
+ env = env_getenv((char*)iocb->plist.iocb_envbuf.name_ptr);
+
+ if (env == NULL) return CFE_ERR_ENVNOTFOUND;
+
+ xstrncpy((char*)iocb->plist.iocb_envbuf.val_ptr,
+ env,
+ iocb->plist.iocb_envbuf.val_length);
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_env_set(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int res;
+ int flg;
+
+
+ flg = (iocb->iocb_flags & CFE_FLG_ENV_PERMANENT) ?
+ ENV_FLG_NORMAL : ENV_FLG_BUILTIN;
+
+ res = env_setenv((char*)iocb->plist.iocb_envbuf.name_ptr,
+ (char*)iocb->plist.iocb_envbuf.val_ptr,
+ flg);
+
+ if (res == 0) {
+ if (iocb->iocb_flags & CFE_FLG_ENV_PERMANENT) res = env_save();
+ }
+
+ if (res < 0) return res;
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_env_del(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int res;
+
+ res = env_delenv((char*)iocb->plist.iocb_envbuf.name_ptr);
+
+ return res;
+}
+
+
+
diff --git a/cfe/cfe/main/cfe_ldr_elf.c b/cfe/cfe/main/cfe_ldr_elf.c
new file mode 100644
index 0000000..0581241
--- /dev/null
+++ b/cfe/cfe/main/cfe_ldr_elf.c
@@ -0,0 +1,396 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * ELF Program Loader File: cfe_ldr_elf.c
+ *
+ * This program parses ELF executables and loads them into memory.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+
+#include "cfe.h"
+#include "cfe_loader.h"
+#include "cfe_fileops.h"
+#include "elf.h"
+
+#include "cfe_boot.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+static int cfe_elfload(cfe_loadargs_t *la);
+
+const cfe_loader_t elfloader = {
+ "elf",
+ cfe_elfload,
+ 0};
+
+/* *********************************************************************
+ * readprogsegment(fsctx,ref,addr,size)
+ *
+ * Read a program segment, generally corresponding to one
+ * section of the file.
+ *
+ * Input parameters:
+ * fsctx - file I/O dispatch
+ * ref - reference data for open file handle
+ * addr - target virtual address
+ * size - size of region to read
+ *
+ * Return value:
+ * Number of bytes copied or <0 if error occured
+ ********************************************************************* */
+
+static int readprogsegment(fileio_ctx_t *fsctx,void *ref,
+ void *addr,int size,int flags)
+{
+ int res;
+
+#ifdef __long64
+ if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size);
+#else
+ if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size);
+#endif
+
+ if (!cfe_arena_loadcheck((uintptr_t) addr,size)) {
+ return CFE_ERR_BADADDR;
+ }
+
+ res = fs_read(fsctx,ref,addr,size);
+
+ if (res < 0) return CFE_ERR_IOERR;
+ if (res != size) return CFE_ERR_BADELFFMT;
+
+ return size;
+}
+
+
+/* *********************************************************************
+ * readclearbss(addr,size)
+ *
+ * Process a BSS section, zeroing memory corresponding to
+ * the BSS.
+ *
+ * Input parameters:
+ * addr - address to zero
+ * size - length of area to zero
+ *
+ * Return value:
+ * number of zeroed bytes or <0 if error occured
+ ********************************************************************* */
+
+static int readclearbss(void *addr,int size,int flags)
+{
+
+#ifdef __long64
+ if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size);
+#else
+ if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size);
+#endif
+
+ if (!cfe_arena_loadcheck((uintptr_t) addr,size)) {
+ return CFE_ERR_BADADDR;
+ }
+
+ if (size > 0) memset(addr,0,size);
+ return size;
+}
+
+
+/* *********************************************************************
+ * elfgetshdr(ops,ref,ep)
+ *
+ * Get a section header from the ELF file
+ *
+ * Input parameters:
+ * ops - file I/O dispatch
+ * ref - reference data for open file
+ * ep - extended header info
+ *
+ * Return value:
+ * copy of section header (malloc'd) or NULL if no memory
+ ********************************************************************* */
+
+static Elf32_Shdr *elfgetshdr(fileio_ctx_t *fsctx,void *ref,Elf32_Ehdr *ep)
+{
+ Elf32_Shdr *shtab;
+ unsigned size = ep->e_shnum * sizeof(Elf32_Shdr);
+
+ shtab = (Elf32_Shdr *) KMALLOC(size,0);
+ if (!shtab) {
+ return NULL;
+ }
+
+ if (fs_seek(fsctx,ref,ep->e_shoff,FILE_SEEK_BEGINNING) != ep->e_shoff ||
+ fs_read(fsctx,ref,(uint8_t *)shtab,size) != size) {
+ KFREE(shtab);
+ return NULL;
+ }
+
+ return (shtab);
+}
+
+/* *********************************************************************
+ * elfload_internal(ops,ref,entrypt,flags)
+ *
+ * Read an ELF file (main routine)
+ *
+ * Input parameters:
+ * ops - file I/O dispatch
+ * ref - open file handle
+ * entrypt - filled in with entry vector
+ * flags - generic boot flags
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int elfload_internal(fileio_ctx_t *fsctx,void *ref,
+ unsigned long *entrypt,int flags)
+{
+ Elf32_Ehdr *ep;
+ Elf32_Phdr *phtab = 0;
+ Elf32_Shdr *shtab = 0;
+ unsigned int nbytes;
+ int i;
+ int res;
+ Elf32_Ehdr ehdr;
+
+ ep = &ehdr;
+ if (fs_read(fsctx,ref,(uint8_t *) ep,sizeof(*ep)) != sizeof(*ep)) {
+ return CFE_ERR_IOERR;
+ }
+
+ /* check header validity */
+ if (ep->e_ident[EI_MAG0] != ELFMAG0 ||
+ ep->e_ident[EI_MAG1] != ELFMAG1 ||
+ ep->e_ident[EI_MAG2] != ELFMAG2 ||
+ ep->e_ident[EI_MAG3] != ELFMAG3) {
+ return CFE_ERR_NOTELF;
+ }
+
+ if (ep->e_ident[EI_CLASS] != ELFCLASS32) return CFE_ERR_NOT32BIT;
+
+#ifdef __MIPSEB
+ if (ep->e_ident[EI_DATA] != ELFDATA2MSB) return CFE_ERR_WRONGENDIAN; /* big endian */
+#endif
+#ifdef __MIPSEL
+ if (ep->e_ident[EI_DATA] != ELFDATA2LSB) return CFE_ERR_WRONGENDIAN; /* little endian */
+#endif
+
+ if (ep->e_ident[EI_VERSION] != EV_CURRENT) return CFE_ERR_BADELFVERS;
+ if (ep->e_machine != EM_MIPS) return CFE_ERR_NOTMIPS;
+
+ /* Is there a program header? */
+ if (ep->e_phoff == 0 || ep->e_phnum == 0 ||
+ ep->e_phentsize != sizeof(Elf32_Phdr)) {
+ return CFE_ERR_BADELFFMT;
+ }
+
+ /* Load program header */
+ nbytes = ep->e_phnum * sizeof(Elf32_Phdr);
+ phtab = (Elf32_Phdr *) KMALLOC(nbytes,0);
+ if (!phtab) {
+ return CFE_ERR_NOMEM;
+ }
+
+ if (fs_seek(fsctx,ref,ep->e_phoff,FILE_SEEK_BEGINNING) != ep->e_phoff ||
+ fs_read(fsctx,ref,(uint8_t *)phtab,nbytes) != nbytes) {
+ KFREE(phtab);
+ return CFE_ERR_IOERR;
+ }
+
+ /*
+ * From now on we've got no guarantee about the file order,
+ * even where the section header is. Hopefully most linkers
+ * will put the section header after the program header, when
+ * they know that the executable is not demand paged. We assume
+ * that the symbol and string tables always follow the program
+ * segments.
+ */
+
+ /* read section table (if before first program segment) */
+ if (ep->e_shoff < phtab[0].p_offset) {
+ shtab = elfgetshdr(fsctx,ref,ep);
+ }
+
+ /* load program segments */
+ /* We cope with a badly sorted program header, as produced by
+ * older versions of the GNU linker, by loading the segments
+ * in file offset order, not in program header order. */
+
+ while (1) {
+ Elf32_Off lowest_offset = ~0;
+ Elf32_Phdr *ph = 0;
+
+ /* find nearest loadable segment */
+ for (i = 0; i < ep->e_phnum; i++)
+ if ((phtab[i].p_type == PT_LOAD) && (phtab[i].p_offset < lowest_offset)) {
+ ph = &phtab[i];
+ lowest_offset = ph->p_offset;
+ }
+ if (!ph) {
+ break; /* none found, finished */
+ }
+
+ /* load the segment */
+ if (ph->p_filesz) {
+ if (fs_seek(fsctx,ref,ph->p_offset,FILE_SEEK_BEGINNING) != ph->p_offset) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return CFE_ERR_BADELFFMT;
+ }
+ res = readprogsegment(fsctx,ref,
+ (void *)(intptr_t)(signed)ph->p_vaddr,
+ ph->p_filesz,flags);
+ if (res != ph->p_filesz) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return res;
+ }
+ }
+
+ if (ph->p_filesz < ph->p_memsz) {
+ res = readclearbss((void *)(intptr_t)(signed)ph->p_vaddr + ph->p_filesz,
+ ph->p_memsz - ph->p_filesz,flags);
+ if (res < 0) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return res;
+ }
+ }
+
+ ph->p_type = PT_NULL; /* remove from consideration */
+ }
+
+ KFREE(phtab);
+
+ *entrypt = (intptr_t)(signed)ep->e_entry; /* return entry point */
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * cfe_elfload(ops,file,flags)
+ *
+ * Read an ELF file (main entry point)
+ *
+ * Input parameters:
+ * ops - fileio dispatch
+ * file - name of file to read
+ * ept - where to put entry point
+ * flags - load flags
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int cfe_elfload(cfe_loadargs_t *la)
+{
+ fileio_ctx_t *fsctx;
+ void *ref;
+ int res;
+
+ /*
+ * Look up the file system type and get a context
+ */
+
+
+ res = fs_init(la->la_filesys,&fsctx,la->la_device);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Turn on compression if we're doing that.
+ */
+
+ if (la->la_flags & LOADFLG_COMPRESSED) {
+ res = fs_hook(fsctx,"z");
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ /*
+ * Open the remote file
+ */
+
+ res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return CFE_ERR_FILENOTFOUND;
+ }
+
+ /*
+ * Load the image.
+ */
+
+ la->la_entrypt = 0;
+ res = elfload_internal(fsctx,ref,&(la->la_entrypt),la->la_flags);
+
+ /*
+ * All done, release resources
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ return res;
+}
+
+
diff --git a/cfe/cfe/main/cfe_ldr_raw.c b/cfe/cfe/main/cfe_ldr_raw.c
new file mode 100644
index 0000000..d436849
--- /dev/null
+++ b/cfe/cfe/main/cfe_ldr_raw.c
@@ -0,0 +1,360 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * RAW Program Loader File: cfe_ldr_raw.c
+ *
+ * This program reads raw binaries into memory.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe.h"
+#include "cfe_fileops.h"
+
+#include "cfe_boot.h"
+#include "cfe_bootblock.h"
+
+#include "cfe_loader.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+static int cfe_rawload(cfe_loadargs_t *la);
+
+const cfe_loader_t rawloader = {
+ "raw",
+ cfe_rawload,
+ 0};
+
+/* *********************************************************************
+ * cfe_findbootblock(la,fsctx,ref)
+ *
+ * Find the boot block on the specified device.
+ *
+ * Input parameters:
+ * la - loader args (to be filled in)
+ * ops - file operations
+ * ref - reference for open file handle
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+static int cfe_findbootblock(cfe_loadargs_t *la,
+ fileio_ctx_t *fsctx,
+ void *ref,
+ struct boot_block *bootblock)
+{
+ uint32_t checksum = 0;
+ uint32_t calcsum;
+ uint32_t secsize = 0;
+ uint64_t secoffset = 0;
+ int res;
+ int curblk;
+
+ /*
+ * Search for the boot block. Stop when we find
+ * something with a matching checksum and magic
+ * number.
+ */
+
+ fs_seek(fsctx,ref,0,FILE_SEEK_BEGINNING);
+
+ for (curblk = 0; curblk < BOOT_BLOCK_MAXLOC; curblk++) {
+
+
+ /* Read a block */
+
+ res = fs_read(fsctx,ref,
+ (unsigned char *) bootblock,
+ sizeof(struct boot_block));
+
+ if (res != sizeof(struct boot_block)) {
+ return CFE_ERR_IOERR;
+ }
+
+ /* Verify magic number */
+
+ if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) {
+ continue;
+ }
+
+ /* Extract fields from block */
+
+ checksum = ((uint32_t) (bootblock->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK));
+ bootblock->bb_hdrinfo &= ~BOOT_HDR_CHECKSUM_MASK;
+ secsize = ((uint32_t) (bootblock->bb_secsize & BOOT_SECSIZE_MASK));
+ secoffset = bootblock->bb_secstart;
+
+ /* Verify block's checksum */
+
+ CHECKSUM_BOOT_DATA(&(bootblock->bb_magic),BOOT_BLOCK_SIZE,&calcsum);
+
+ if (checksum == calcsum) {
+ break;
+ }
+ }
+
+ /*
+ * Okay, determine if we were successful.
+ */
+
+ if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) {
+ return CFE_ERR_INVBOOTBLOCK;
+ }
+
+ if (checksum != calcsum) {
+ return CFE_ERR_BBCHECKSUM;
+ }
+
+ /*
+ * If we get here, we had a valid boot block.
+ */
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * cfe_rawload(la)
+ *
+ * Read a raw (unformatted) boot file
+ *
+ * Input parameters:
+ * la - loader args
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+static int cfe_rawload(cfe_loadargs_t *la)
+{
+ int res;
+ fileio_ctx_t *fsctx;
+ const fileio_dispatch_t *ops;
+ void *ref;
+ int ttlcopy = 0;
+ int findbb;
+ int devinfo;
+ struct boot_block bootblock;
+ uint8_t *ptr;
+ uint8_t *bootcode;
+ uint32_t checksum,calcsum;
+ uint64_t secoffset = 0;
+ int32_t maxsize;
+ int amtcopy;
+ int thisamt;
+ uint32_t loadflags;
+ int onedot;
+
+ loadflags = la->la_flags;
+
+ /*
+ * Set starting address and maximum size. You can either
+ * explicitly set this (with LOADFLG_SPECADDR) or
+ * let CFE decide. If CFE decides, the load address
+ * will be BOOT_START_ADDRESS in all cases.
+ * The size is dependant on the device type: block and flash
+ * devices will get this info from the boot block,
+ * and network devices will get the info by reaching EOF
+ * on reads, up to the maximum size of the boot area.
+ */
+
+ if (loadflags & LOADFLG_SPECADDR) {
+ bootcode = (uint8_t *) la->la_address;
+ maxsize = la->la_maxsize;
+ findbb = FALSE; /* don't find a boot block */
+ }
+ else {
+ bootcode = (uint8_t *) BOOT_START_ADDRESS;
+ maxsize = BOOT_AREA_SIZE;
+ findbb = FALSE;
+ devinfo = la->la_device ? cfe_getdevinfo(la->la_device) : 0;
+
+ /*
+ * If the device is either a disk or a flash device,
+ * we will expect to find a boot block.
+ * Serial and network devices do not have boot blocks.
+ */
+ if ((devinfo >= 0) &&
+ ( ((devinfo & CFE_DEV_MASK) == CFE_DEV_DISK) ||
+ ((devinfo & CFE_DEV_MASK) == CFE_DEV_FLASH) )) {
+ findbb = TRUE;
+ }
+ }
+
+
+ /*
+ * merge in any filesystem-specific flags
+ */
+
+ ops = cfe_findfilesys(la->la_filesys);
+ if (!ops) return CFE_ERR_FSNOTAVAIL;
+ loadflags |= ops->loadflags;
+
+ /*
+ * turn off the boot block if requested.
+ */
+
+ if (loadflags & LOADFLG_NOBB) findbb = FALSE;
+
+ /*
+ * Create a file system context
+ */
+
+ res = fs_init(la->la_filesys,&fsctx,la->la_device);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Turn on compression if we're doing that.
+ */
+
+ if (!findbb && (la->la_flags & LOADFLG_COMPRESSED)) {
+ res = fs_hook(fsctx,"z");
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ /*
+ * Open the boot device
+ */
+
+ res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ /*
+ * If we need to find a boot block, do it now.
+ */
+
+ if (findbb) {
+ res = cfe_findbootblock(la,fsctx,ref,&bootblock);
+
+ /*
+ * If we found the boot block, seek to the part of the
+ * disk where the boot code is.
+ * Otherwise, get out now, since the disk has no boot block.
+ */
+
+ if (res == 0) {
+ maxsize = (int) ((uint32_t) (bootblock.bb_secsize & BOOT_SECSIZE_MASK));
+ secoffset = bootblock.bb_secstart;
+ fs_seek(fsctx,ref,secoffset,FILE_SEEK_BEGINNING);
+ }
+ else {
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ }
+
+ /*
+ * Okay, go load the boot file.
+ */
+
+ ptr = bootcode;
+ amtcopy = maxsize;
+ ttlcopy = 0;
+
+ onedot = amtcopy / 10; /* ten dots for entire load */
+ if (onedot < 4096) onedot = 4096; /* but minimum 4096 bytes per dot */
+ onedot = (onedot + 1) & ~4095; /* round to multiple of 4096 */
+
+ while (amtcopy > 0) {
+ thisamt = onedot;
+ if (thisamt > amtcopy) thisamt = amtcopy;
+
+ res = fs_read(fsctx,ref,ptr,thisamt);
+ if (la->la_flags & LOADFLG_NOISY) {
+ xprintf(".");
+ }
+ if (res <= 0) break;
+ ptr += res;
+ amtcopy -= res;
+ ttlcopy += res;
+ }
+
+ /*
+ * We're done with the file.
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ /*
+ * Verify the boot loader checksum if we were reading
+ * the disk.
+ */
+
+ if (findbb) {
+ CHECKSUM_BOOT_DATA(bootcode,maxsize,&calcsum);
+ checksum = (uint32_t) ((bootblock.bb_secsize & BOOT_DATA_CHECKSUM_MASK)
+ >> BOOT_DATA_CHECKSUM_SHIFT);
+
+ if (checksum != calcsum) {
+ return CFE_ERR_BOOTPROGCHKSUM;
+ }
+ }
+
+ la->la_entrypt = (uintptr_t) bootcode;
+
+ if (la->la_flags & LOADFLG_NOISY) xprintf(" %d bytes read\n",ttlcopy);
+
+ return (res < 0) ? res : ttlcopy;
+
+}
+
diff --git a/cfe/cfe/main/cfe_ldr_srec.c b/cfe/cfe/main/cfe_ldr_srec.c
new file mode 100644
index 0000000..b067f2b
--- /dev/null
+++ b/cfe/cfe/main/cfe_ldr_srec.c
@@ -0,0 +1,557 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * SREC Program Loader File: cfe_ldr_srec.c
+ *
+ * This program reads Motorola S-record files into memory
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe.h"
+#include "cfe_fileops.h"
+
+#include "cfe_boot.h"
+#include "cfe_bootblock.h"
+
+#include "cfe_loader.h"
+
+#include "cfe_mem.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+static int cfe_srecload(cfe_loadargs_t *la);
+
+const cfe_loader_t srecloader = {
+ "srec",
+ cfe_srecload,
+ 0};
+
+
+typedef struct linebuf_s {
+ char linebuf[256];
+ int curidx;
+ int buflen;
+ int eof;
+ void *ref;
+ fileio_ctx_t *fsctx;
+} linebuf_t;
+
+#define initlinebuf(b,r,o) (b)->curidx = 0; (b)->buflen = 0; \
+ (b)->eof = 0 ; (b)->ref = r; (b)->fsctx = o
+
+
+/* *********************************************************************
+ * readchar(file)
+ *
+ * Read a character from a file. It's kind of like getchar
+ * on "C" FILE devices, but not so fancy.
+ *
+ * Input parameters:
+ * file - pointer to a linebuf_t containing reader state
+ *
+ * Return value:
+ * character, or -1 if at EOF
+ ********************************************************************* */
+
+static int readchar(linebuf_t *file)
+{
+ int ch;
+ int res;
+
+ if (file->eof) return -1;
+
+ if (file->curidx == file->buflen) {
+ for (;;) {
+ res = fs_read(file->fsctx,file->ref,file->linebuf,sizeof(file->linebuf));
+ if (res < 0) {
+ file->eof = -1;
+ return -1;
+ }
+ if (res == 0) continue;
+ file->buflen = res;
+ file->curidx = 0;
+ break;
+ }
+ }
+
+ ch = file->linebuf[file->curidx];
+ file->curidx++;
+ return ch;
+}
+
+
+/* *********************************************************************
+ * readline(file,buffer,maxlen)
+ *
+ * Read a line of text from a file using our crude file stream
+ * mechanism.
+ *
+ * Input parameters:
+ * file - pointer to a linebuf_t containing reader state
+ * buffer - will receive line of text
+ * maxlen - number of bytes that will fit in buffer
+ *
+ * Return value:
+ * 0 if ok, else <0 if at EOF
+ ********************************************************************* */
+
+static int readline(linebuf_t *file,char *buffer,int maxlen)
+{
+ int ch;
+ char *ptr;
+
+ ptr = buffer;
+ maxlen--; /* account for terminating null */
+
+ while (maxlen) {
+ ch = readchar(file);
+ if (ch == -1) return -1;
+ if (ch == 27) return -1; /* ESC */
+ if ((ch == '\n') || (ch == '\r')) break;
+ *ptr++ = (char) ch;
+ maxlen--;
+ }
+
+ *ptr = '\0';
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * getxdigit(c)
+ *
+ * Convert a hex digit into its numeric equivalent
+ *
+ * Input parameters:
+ * c - character
+ *
+ * Return value:
+ * value
+ ********************************************************************* */
+
+static int getxdigit(char c)
+{
+ if ((c >= '0') && (c <= '9')) return c - '0';
+ if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
+ if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10;
+ return -1;
+}
+
+/* *********************************************************************
+ * getbyte(line)
+ *
+ * Process two hex digits and return the value
+ *
+ * Input parameters:
+ * line - pointer to pointer to characters (updated on exit)
+ *
+ * Return value:
+ * byte value, or <0 if bad hex digits
+ ********************************************************************* */
+
+static int getbyte(char **line)
+{
+ int res;
+ int c1,c2;
+
+ c1 = getxdigit(*(*(line)+0));
+ if (c1 < 0) return -1;
+
+ c2 = getxdigit(*(*(line)+1));
+ if (c2 < 0) return -1;
+
+ res = (c1*16+c2);
+ (*line) += 2;
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * procsrec(line,loadaddr,blklen,data)
+ *
+ * Process an S-record, reading the data into a local buffer
+ * and returning the block's address.
+ *
+ * Input parameters:
+ * line - line of text (s-record line)
+ * loadaddr - will be filled with address where data should go
+ * blklen - will be filled in with size of record
+ * data - points to buffer to receive data
+ *
+ * Return value:
+ * <0 if error occured (not an s-record)
+ ********************************************************************* */
+
+static int procsrec(char *line,
+ unsigned int *loadaddr,
+ unsigned int *blklen,
+ unsigned char *data)
+{
+ char rectype;
+ unsigned char b;
+ unsigned int len;
+ unsigned int minlen;
+ unsigned int linelen;
+ unsigned int addr;
+ unsigned int chksum;
+
+ int idx;
+ int ret = 0;
+
+ addr = 0;
+
+ if (*line++ != 'S')
+ return -1; /* not an S record */
+
+ rectype = *line++;
+
+ minlen = 3; /* type 1 record */
+ switch (rectype) {
+ case '0':
+ break;
+
+ /*
+ * data bytes
+ */
+ case '3':
+ minlen++;
+ /* fall through */
+ case '2':
+ minlen++;
+ /* fall through */
+ case '1':
+ chksum = 0;
+ linelen = getbyte(&line);
+ if (linelen < minlen) {
+ xprintf("srec: line too short\n");
+ return -1;
+ }
+ chksum += (unsigned int)linelen;
+
+ /*
+ * There are two address bytes in a type 1 record, and three
+ * in a type 2 record. The high-order byte is first, then
+ * one or two lower-order bytes. Build up the adddress.
+ */
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr = b;
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr <<= 8;
+ addr += b;
+ if (rectype == '2') {
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr <<= 8;
+ addr += b;
+ }
+ if (rectype == '3') {
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr <<= 8;
+ addr += b;
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr <<= 8;
+ addr += b;
+ }
+
+#if VERBOSE
+ printf("Addr: %08X Len: %3u(0x%x)\n", addr , linelen - minlen,
+ linelen-minlen);
+#endif
+
+ *loadaddr = addr;
+ len = linelen - minlen;
+ *blklen = len;
+
+ for (idx = 0; idx < len; idx++) {
+ b = getbyte(&line);
+ chksum += (unsigned int) b;
+ data[idx] = (unsigned char ) b;
+ }
+
+ b = getbyte(&line);
+ chksum = (~chksum) & 0x000000FF;
+ if (chksum != b) {
+ xprintf("Checksum error in s-record file\n");
+ return -1;
+ }
+ ret = 1;
+ break;
+
+ case '9':
+ linelen = getbyte(&line);
+ b = getbyte(&line);
+ addr = b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ *loadaddr = addr;
+ ret = -2;
+ break;
+
+ case '8':
+ linelen = getbyte(&line);
+ b = getbyte(&line);
+ addr = b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ *loadaddr = addr;
+ ret = -2;
+ break;
+
+ case '7':
+ linelen = getbyte(&line);
+ b = getbyte(&line);
+ addr = b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ *loadaddr = addr;
+ ret = -2;
+ break;
+
+ default:
+ xprintf("Unknown S-record type: %c\n",rectype);
+ return -1;
+ break;
+ }
+
+ return ret;
+}
+
+
+/* *********************************************************************
+ * cfe_srecload(la)
+ *
+ * Read an s-record file
+ *
+ * Input parameters:
+ * la - loader args
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+static int cfe_srecload(cfe_loadargs_t *la)
+{
+ int res;
+ fileio_ctx_t *fsctx;
+ void *ref;
+ int devinfo;
+ int serial = FALSE;
+ unsigned int loadaddr;
+ unsigned int blklen;
+ linebuf_t lb;
+ char line[256];
+ uint8_t data[256];
+ int cnt;
+ unsigned int specaddr; /* current address if loading to a special address */
+ int specflg; /* true if in "special address" mode */
+ int firstrec = 1; /* true if we have not seen the first record */
+
+ /*
+ * We might want to know something about the boot device.
+ */
+
+ devinfo = la->la_device ? cfe_getdevinfo(la->la_device) : 0;
+
+ /*
+ * Figure out if we're loading to a "special address". This lets
+ * us load S-records into a temporary buffer, ignoring the
+ * addresses in the records (but using them so we'll know where
+ * they go relative to each other
+ */
+
+ specflg = (la->la_flags & LOADFLG_SPECADDR) ? 1 : 0;
+ specaddr = 0;
+
+ /*
+ * If the device is a serial port, we want to know that.
+ */
+
+ if ((devinfo >= 0) &&
+ ((devinfo & CFE_DEV_MASK) == CFE_DEV_SERIAL)) {
+ serial = TRUE;
+ }
+
+ /*
+ * Create a file system context
+ */
+
+ res = fs_init(la->la_filesys,&fsctx,la->la_device);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Turn on compression if we're doing that.
+ */
+
+ if (la->la_flags & LOADFLG_COMPRESSED) {
+ res = fs_hook(fsctx,"z");
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ /*
+ * Open the boot device
+ */
+
+ res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ /*
+ * Okay, go load the boot file. Process S-records until
+ * we get an entry point record (usually at the end).
+ *
+ * XXX what if it's *not* at the end?
+ */
+
+ initlinebuf(&lb,ref,fsctx);
+
+ cnt = 0;
+ for (;;) {
+ /*
+ * Read a line of text
+ */
+ res = readline(&lb,line,sizeof(line));
+ if (res < 0) break; /* reached EOF */
+
+ /*
+ * Process the S-record. If at EOF, procsrec returns 0.
+ * Invalid s-records returns -1.
+ */
+
+ if (line[0] == 0) continue;
+
+ res = procsrec(line,&loadaddr,&blklen,data);
+
+#if 0
+ if (res == -2 || res >= 0)
+ xprintf(".");
+#endif
+ if (res < 0) break;
+
+ /*
+ * Handle "special address" mode. All S-records will be
+ * loaded into a buffer passed by the caller to the loader.
+ * We use the addresses in the S-records to determine
+ * relative placement of the data, keying on the first
+ * S-record in the file.
+ */
+
+ if ((res == 1) && (specflg)) {
+ if (firstrec) {
+ /* First S-record seen sets the base for all that follow */
+ specaddr = loadaddr;
+ firstrec = 0;
+ }
+ loadaddr = la->la_address + (intptr_t) (loadaddr - specaddr);
+ }
+
+ cnt++;
+
+ if (res == 1) {
+ if (!cfe_arena_loadcheck((intptr_t) loadaddr,blklen)) {
+ xprintf("Invalid address: %P\n",loadaddr);
+ res = -1;
+ break;
+ }
+ memcpy((uint8_t *) (intptr_t) (signed)loadaddr,data,blklen);
+ }
+ }
+
+ /*
+ * We're done with the file.
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ /*
+ * Say something cute on the LEDs.
+ * Don't do this for every s-record, because if logging the LED
+ * changes out the serial port, that can take a Long Time. Just
+ * goes to show: too much cuteness is a _very_ bad thing.
+ */
+ xsprintf(line,"%04d",cnt);
+ cfe_ledstr(line);
+
+ if (res == -2) {
+ la->la_entrypt = (intptr_t) (signed) loadaddr;
+ res = 0;
+ }
+
+ return res;
+}
+
+
diff --git a/cfe/cfe/main/cfe_link.mk b/cfe/cfe/main/cfe_link.mk
new file mode 100644
index 0000000..7529dc4
--- /dev/null
+++ b/cfe/cfe/main/cfe_link.mk
@@ -0,0 +1,26 @@
+#
+# This Makefile snippet takes care of linking the firmware.
+#
+
+pci : $(PCICOMMON) $(PCIMACHDEP)
+ echo done
+
+cfe cfe.bin : $(CRT0OBJS) $(BSPOBJS) $(LIBCFE)
+ $(GLD) -o cfe -Map cfe.map $(LDFLAGS) $(CRT0OBJS) $(BSPOBJS) -L. -lcfe $(LDLIBS)
+ $(OBJDUMP) -d cfe > cfe.dis
+ $(OBJCOPY) --output-target=binary cfe cfe.bin
+ $(OBJCOPY) --input-target=binary --output-target=srec cfe.bin cfe.srec
+
+cfe.flash : cfe.bin mkflashimage
+ ./mkflashimage -v ${ENDIAN} -B ${CFG_BOARDNAME} -V ${CFE_VER_MAJ}.${CFE_VER_MIN}.${CFE_VER_ECO} cfe.bin cfe.flash
+ $(OBJCOPY) --input-target=binary --output-target=srec cfe.flash cfe.flash.srec
+
+
+clean :
+ rm -f *.o *~ cfe cfe.bin cfe.dis cfe.map cfe.srec
+ rm -f makereg ${CPU}_socregs.inc mkpcidb pcidevs_data2.h mkflashimage
+ rm -f build_date.c
+ rm -f libcfe.a
+ rm -f cfe.flash cfe.flash.srec $(CLEANOBJS)
+
+distclean : clean
diff --git a/cfe/cfe/main/cfe_loader.c b/cfe/cfe/main/cfe_loader.c
new file mode 100644
index 0000000..bbd3eb4
--- /dev/null
+++ b/cfe/cfe/main/cfe_loader.c
@@ -0,0 +1,135 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Loader API File: cfe_loader.c
+ *
+ * This is the main API for the program loader. CFE supports
+ * multiple "installable" methods for loading programs, allowing
+ * us to deal with a variety of methods for moving programs
+ * into memory for execution.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+
+#include "cfe.h"
+#include "cfe_fileops.h"
+
+#include "cfe_loader.h"
+
+#include "bsp_config.h"
+
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern const cfe_loader_t elfloader;
+extern const cfe_loader_t rawloader;
+extern const cfe_loader_t srecloader;
+
+/* *********************************************************************
+ * Loader list
+ ********************************************************************* */
+
+const cfe_loader_t * const cfe_loaders[] = {
+ &elfloader,
+#if !CFG_MINIMAL_SIZE
+ &rawloader,
+ &srecloader,
+#endif
+ NULL};
+
+/* *********************************************************************
+ * cfe_findloader(name)
+ *
+ * Find a loader by name
+ *
+ * Input parameters:
+ * name - name of loader to find
+ *
+ * Return value:
+ * pointer to loader structure or NULL
+ ********************************************************************* */
+
+const cfe_loader_t *cfe_findloader(char *name)
+{
+ const cfe_loader_t * const *ldr;
+
+ ldr = cfe_loaders;
+
+ while (*ldr) {
+ if (strcmp(name,(*ldr)->name) == 0) return (*ldr);
+ ldr++;
+ }
+
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * cfe_load_progam(name,args)
+ *
+ * Look up a loader and call it.
+ *
+ * Input parameters:
+ * name - name of loader to run
+ * args - arguments to pass
+ *
+ * Return value:
+ * return value
+ ********************************************************************* */
+
+int cfe_load_program(char *name,cfe_loadargs_t *la)
+{
+ const cfe_loader_t *ldr;
+ int res;
+
+ ldr = cfe_findloader(name);
+ if (!ldr) return CFE_ERR_LDRNOTAVAIL;
+
+ res = LDRLOAD(ldr,la);
+
+ return res;
+}
diff --git a/cfe/cfe/main/cfe_main.c b/cfe/cfe/main/cfe_main.c
new file mode 100644
index 0000000..1a451a6
--- /dev/null
+++ b/cfe/cfe/main/cfe_main.c
@@ -0,0 +1,636 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Main Module File: cfe_main.c
+ *
+ * This module contains the main "C" routine for CFE and
+ * the main processing loop. There should not be any board-specific
+ * stuff in here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_timer.h"
+
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe_mem.h"
+#include "cfe.h"
+
+#include "exception.h"
+
+#include "bsp_config.h"
+
+#include "segtable.h"
+
+#include "initdata.h"
+
+#if CFG_PCI
+#include "pcivar.h"
+#endif
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#ifndef CFG_STACK_SIZE
+#define STACK_SIZE 8192
+#else
+#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)
+#endif
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+void cfe_main(int,int);
+extern void cfe_device_poll(void *x);
+
+extern int ui_init_envcmds(void);
+extern int ui_init_devcmds(void);
+extern int ui_init_netcmds(void);
+extern int ui_init_memcmds(void);
+extern int ui_init_loadcmds(void);
+extern int ui_init_pcicmds(void);
+extern int ui_init_examcmds(void);
+extern int ui_init_flashcmds(void);
+extern int ui_init_misccmds(void);
+#if CFG_VAPI
+extern int ui_init_vapicmds(void);
+#endif
+
+#if CFG_VENDOR_EXTENSIONS
+extern int ui_init_vendorcmds(void);
+#endif
+
+void cfe_command_restart(uint64_t status);
+
+extern segtable_t *_getsegtbl(void);
+
+extern const char *builddate;
+extern const char *builduser;
+
+#if CFG_MULTI_CPUS
+extern int altcpu_cmd_start(uint64_t,uint64_t *);
+extern int altcpu_cmd_stop(uint64_t);
+#endif
+
+
+
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+const char *cfe_boardname = CFG_BOARDNAME;
+unsigned int cfe_startflags =
+#if CFG_PCI
+ CFE_INIT_PCI |
+#endif
+ 0;
+
+/* *********************************************************************
+ * cfe_setup_default_env()
+ *
+ * Initialize the default environment for CFE. These are all
+ * the temporary variables that do not get stored in the NVRAM
+ * but are available to other programs and command-line macros.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void cfe_setup_default_env(void)
+{
+ char buffer[80];
+
+ xsprintf(buffer,"%d.%d.%d",CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD);
+ env_setenv("CFE_VERSION",buffer,ENV_FLG_BUILTIN | ENV_FLG_READONLY);
+
+ if (cfe_boardname) {
+ env_setenv("CFE_BOARDNAME",(char *) cfe_boardname,
+ ENV_FLG_BUILTIN | ENV_FLG_READONLY);
+ }
+
+ xsprintf(buffer,"%d",mem_totalsize);
+ env_setenv("CFE_MEMORYSIZE",buffer,ENV_FLG_BUILTIN | ENV_FLG_READONLY);
+
+}
+
+
+/* *********************************************************************
+ * cfe_init_ui()
+ *
+ * Call all the other UI initialization modules. Each of these
+ * modules usually calls back to the UI dispatcher to add command
+ * tables.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#if CFG_MINIMAL_SIZE
+#define OPTIONAL(x)
+#else
+#define OPTIONAL(x) x
+#endif
+
+static void cfe_init_ui(void)
+{
+ ui_init_cmddisp();
+
+ ui_init_envcmds();
+ OPTIONAL(ui_init_devcmds());
+#if CFG_NETWORK
+ ui_init_netcmds();
+#endif
+ ui_init_loadcmds();
+ OPTIONAL(ui_init_memcmds());
+
+#if CFG_PCI
+ ui_init_pcicmds();
+#endif
+ OPTIONAL(ui_init_examcmds());
+ ui_init_flashcmds();
+#if CFG_VAPI
+ ui_init_vapicmds();
+#endif
+
+#if CFG_VENDOR_EXTENSIONS
+ ui_init_vendorcmds();
+#endif
+
+ OPTIONAL(ui_init_misccmds());
+
+}
+
+
+/* *********************************************************************
+ * cfe_ledstr(leds)
+ *
+ * Display a string on the board's LED display, if it has one.
+ * This routine depends on the board-support package to
+ * include a "driver" to write to the actual LED, if the board
+ * does not have one this routine will do nothing.
+ *
+ * The LEDs are written at various places in the initialization
+ * sequence, to debug board problems.
+ *
+ * Input parameters:
+ * leds - pointer to four-character ASCII string
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_ledstr(const char *leds)
+{
+ unsigned int val;
+
+ val = ((((unsigned int) leds[0]) << 24) |
+ (((unsigned int) leds[1]) << 16) |
+ (((unsigned int) leds[2]) << 8) |
+ ((unsigned int) leds[3]));
+
+ cfe_leds(val);
+}
+
+
+/* *********************************************************************
+ * cfe_say_hello()
+ *
+ * Print out the CFE startup message and copyright notice
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+static void cfe_say_hello(void)
+{
+ xprintf("\n\n");
+ xprintf("CFE version 2.0.2"
+#ifdef CFE_VER_RELEASE
+ ".%d"
+#endif
+ " for DGN2200v2 (%s)\n",
+ //CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD,
+#ifdef CFE_VER_RELEASE
+ CFE_VER_RELEASE,
+#endif
+ //cfe_boardname,
+#ifdef __long64
+ "64bit,"
+#else
+ "32bit,"
+#endif
+#if CFG_MULTI_CPUS
+ "MP,"
+#else
+ "SP,"
+#endif
+#ifdef __MIPSEL
+ "LE"
+#endif
+#ifdef __MIPSEB
+ "BE"
+#endif
+#if CFG_VAPI
+ ",VAPI"
+#endif
+ );
+
+ xprintf("Build Date: %s (%s)\n",builddate,builduser);
+ xprintf("Copyright (C) 2000,2001,2002,2003 Broadcom Corporation.\n");
+ xprintf("\n");
+}
+
+
+/* *********************************************************************
+ * cfe_restart()
+ *
+ * Restart CFE from scratch, jumping back to the boot vector.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_restart(void)
+{
+ _exc_restart();
+}
+
+
+/* *********************************************************************
+ * cfe_start(ept)
+ *
+ * Start a user program
+ *
+ * Input parameters:
+ * ept - entry point
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void cfe_start(unsigned long ept)
+{
+ SETLEDS("RUN!");
+ cfe_launch(ept);
+}
+
+
+/* *********************************************************************
+ * cfe_startup_info()
+ *
+ * Display startup memory configuration messages
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void cfe_startup_info(void)
+{
+ segtable_t *segtbl;
+
+ segtbl = _getsegtbl();
+ xprintf("CPU type 0x%X: ",(uint32_t)cpu_prid);
+ if (cfe_cpu_speed < 1000000) xprintf("%dKHz\n",cfe_cpu_speed/1000);
+ else xprintf("%dMHz\n",cfe_cpu_speed/1000000);
+ xprintf("Total memory: 0x%llX bytes (%dMB)\n",
+ (((uint64_t)mem_totalsize) << 20),(uint32_t)mem_totalsize);
+
+ xprintf("\n");
+ xprintf("Total memory used by CFE: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t) mem_bottomofmem,
+ (uint32_t) mem_topofmem,
+ (uint32_t) mem_topofmem-mem_bottomofmem);
+ xprintf("Initialized Data: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t) (segtbl[R_SEG_FDATA] + mem_datareloc),
+ (uint32_t) (segtbl[R_SEG_EDATA] + mem_datareloc),
+ (uint32_t) (segtbl[R_SEG_EDATA] - segtbl[R_SEG_FDATA]));
+ xprintf("BSS Area: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t) (segtbl[R_SEG_FBSS] + mem_datareloc),
+ (uint32_t) (segtbl[R_SEG_END] + mem_datareloc),
+ (uint32_t) (segtbl[R_SEG_END] - segtbl[R_SEG_FBSS]));
+ xprintf("Local Heap: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t)(mem_heapstart),
+ (uint32_t)(mem_heapstart + (CFG_HEAP_SIZE*1024)),
+ (CFG_HEAP_SIZE*1024));
+ xprintf("Stack Area: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t)(mem_heapstart + (CFG_HEAP_SIZE*1024)),
+ (uint32_t)(mem_heapstart + (CFG_HEAP_SIZE*1024) + STACK_SIZE),
+ STACK_SIZE);
+ xprintf("Text (code) segment: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t)mem_textbase,
+ (uint32_t)(mem_textbase+mem_textsize),
+ (uint32_t) mem_textsize);
+ xprintf("Boot area (physical): 0x%08X - 0x%08X\n",
+ mem_bootarea_start,mem_bootarea_start+mem_bootarea_size);
+ xprintf("Relocation Factor: I:%08X - D:%08X\n",
+ (uint32_t) mem_textreloc,(uint32_t) mem_datareloc);
+
+}
+
+
+/* *********************************************************************
+ * cfe_autostart()
+ *
+ * Process automatic commands at startup
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void cfe_autostart(void)
+{
+ char *env;
+ int noauto = 0;
+ char ch;
+
+ env = env_getenv("STARTUP");
+ if (!env) return;
+
+ while (console_status()) {
+ console_read(&ch,1);
+ if (ch == 3) noauto = TRUE; /* Ctrl-C means no auto */
+ }
+
+ if (noauto) {
+ xprintf("Automatic startup canceled via Ctrl-C\n");
+ return;
+ }
+
+ ui_docommands(env);
+}
+
+/* *********************************************************************
+ * cfe_main(a,b)
+ *
+ * It's gotta start somewhere.
+ *
+ * Input parameters:
+ * a,b - not used
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_main(int a,int b)
+{
+
+ /*
+ * By the time this routine is called, the following things have
+ * already been done:
+ *
+ * 1. The processor(s) is(are) initialized.
+ * 2. The caches are initialized.
+ * 3. The memory controller is initialized.
+ * 4. BSS has been zeroed.
+ * 5. The data has been moved to R/W space.
+ * 6. The "C" Stack has been initialized.
+ */
+
+ cfe_bg_init(); /* init background processing */
+ cfe_attach_init();
+ cfe_timer_init(); /* Timer process */
+ cfe_bg_add(cfe_device_poll,NULL);
+
+ /*
+ * Initialize the memory allocator
+ */
+
+ SETLEDS("KMEM");
+ KMEMINIT((unsigned char *) (uintptr_t) mem_heapstart,
+ ((CFG_HEAP_SIZE)*1024));
+
+ /*
+ * Initialize the console. It is done before the other devices
+ * get turned on. The console init also sets the variable that
+ * contains the CPU speed.
+ */
+
+ SETLEDS("CONS");
+ board_console_init();
+
+ /*
+ * Set up the exception vectors
+ */
+
+ cfe_setup_exceptions();
+
+ /*
+ * Say hello.
+ */
+
+ SETLEDS("CIOK");
+ cfe_say_hello();
+
+ /*
+ * Initialize the other devices.
+ */
+
+ SETLEDS("AREN");
+ xprintf("Initializing Arena.\n");
+ cfe_arena_init();
+
+#if CFG_PCI
+ if (cfe_startflags & CFE_INIT_PCI) {
+ pci_flags_t flags = PCI_FLG_NORMAL | PCI_FLG_LDT_PREFETCH;
+ char *str;
+ extern cons_t pci_optnames[];
+
+ flags = PCI_FLG_NORMAL | PCI_FLG_LDT_PREFETCH;
+#if CFG_LDT_REV_017
+ flags |= PCI_FLG_LDT_REV_017;
+#endif
+ str = env_getenv("PCI_OPTIONS");
+ setoptions(pci_optnames,str,&flags);
+
+ xprintf("Initializing PCI. [%s]\n",str ? str : "normal");
+ pci_configure(flags);
+ }
+#endif
+
+ SETLEDS("DEVI");
+ xprintf("Initializing Devices.\n");
+ board_device_init();
+
+ cfe_startup_info();
+ SETLEDS("ENVI");
+ cfe_setup_default_env();
+
+ xprintf("\n");
+
+ cfe_init_ui();
+
+ board_final_init();
+
+ cfe_autostart();
+
+ cfe_command_loop();
+}
+
+/* *********************************************************************
+ * cfe_command_restart()
+ *
+ * This routine is called when an application wants to restart
+ * the firmware's command processor. Reopen the console and
+ * jump back into the command loop.
+ *
+ * Input parameters:
+ * status - A0 value of program returning to firmware
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_command_restart(uint64_t status)
+{
+ /*
+ * Stop alternate CPU(s). If they're already stopped, this
+ * command will make sure they're stopped.
+ */
+
+#if CFG_MULTI_CPUS
+ altcpu_cmd_stop(1); /* stop CPU 1 (XXX more CPUs?) */
+#endif
+
+ /*
+ * Call board reset functions
+ */
+ board_device_reset();
+
+ /*
+ * Reset devices
+ */
+ cfe_device_reset();
+
+ /*
+ * Reset timers
+ */
+ cfe_timer_init();
+
+ /*
+ * Reopen console
+ */
+ console_open(console_name);
+
+ /*
+ * Display program return status
+ */
+
+ xprintf("*** program exit status = %d\n", (int)status);
+
+ /*
+ * Back to processing user commands
+ */
+ cfe_command_loop();
+}
+
+
+
+/* *********************************************************************
+ * cfe_command_loop()
+ *
+ * This routine reads and processes user commands
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_command_loop()
+{
+ char buffer[300];
+ int status;
+ char *prompt;
+
+ SETLEDS("CFE ");
+
+ for (;;) {
+ prompt = env_getenv("PROMPT");
+#if CFG_RAMAPP
+ SETLEDS("CFE*");
+ if (!prompt) prompt = "CFE_RAM> ";
+#else
+ if (!prompt) prompt = "CFE> ";
+#endif
+ console_readline(prompt,buffer,sizeof(buffer));
+
+ status = ui_docommands(buffer);
+
+ if (status != CMD_ERR_BLANK) {
+ xprintf("*** command status = %d\n", status);
+ }
+ }
+}
+
+
+
+
+
diff --git a/cfe/cfe/main/cfe_mem.c b/cfe/cfe/main/cfe_mem.c
new file mode 100644
index 0000000..1c424e1
--- /dev/null
+++ b/cfe/cfe/main/cfe_mem.c
@@ -0,0 +1,256 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Physical Memory (arena) manager File: cfe_mem.c
+ *
+ * This module describes the physical memory available to the
+ * firmware.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_arena.h"
+
+#include "cfe_error.h"
+
+#include "cfe.h"
+#include "cfe_mem.h"
+
+#include "initdata.h"
+
+#define _NOPROTOS_
+#include "cfe_boot.h"
+#undef _NOPROTOS_
+
+#include "cpu_config.h" /* for definition of CPUCFG_ARENAINIT */
+
+#include "addrspace.h" /* for macros dealing with addresses */
+
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define ARENA_RANGE(bottom,top,type) arena_markrange(&cfe_arena,(uint64_t)(bottom), \
+ (uint64_t)(top)-(uint64_t)bottom+1,(type),NULL)
+
+#define MEG (1024*1024)
+#define KB 1024
+#define PAGESIZE 4096
+#define CFE_BOOTAREA_SIZE (256*KB)
+#define CFE_BOOTAREA_ADDR 0x20000000
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+arena_t cfe_arena;
+extern void _setcontext(int64_t);
+
+unsigned int mem_bootarea_start;
+unsigned int mem_bootarea_size;
+
+extern void CPUCFG_ARENAINIT(void);
+extern void cfe_bootarea_init(void);
+extern void CPUCFG_PAGETBLINIT(uint64_t *ptaddr,unsigned int ptstart);
+
+
+
+/* *********************************************************************
+ * cfe_arena_init()
+ *
+ * Create the initial map of physical memory
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_arena_init(void)
+{
+ uint64_t memlo,memhi;
+
+ /*
+ * This macro expands via cpu_config.h to an appropriate function
+ * name for creating an empty arena appropriately for our CPU
+ */
+
+ CPUCFG_ARENAINIT();
+
+ /*
+ * Round the area used by the firmware to a page boundary and
+ * mark it in use
+ */
+
+ memhi = PHYSADDR((mem_topofmem + 4095) & ~4095);
+ memlo = PHYSADDR(mem_bottomofmem) & ~4095;
+
+ ARENA_RANGE(memlo,memhi-1,MEMTYPE_DRAM_USEDBYFIRMWARE);
+
+ /*
+ * Create the initial page table
+ */
+
+ cfe_bootarea_init();
+
+}
+
+
+/* *********************************************************************
+ * cfe_arena_enum(idx,type,start,size)
+ *
+ * Enumerate available memory. This is called by the user
+ * API dispatcher so that operating systems can determine what
+ * memory regions are available to them.
+ *
+ * Input parameters:
+ * idx - index. Start at zero and increment until an error
+ * is returned.
+ * type,start,size: pointers to variables to receive the
+ * arena entry's information
+ * allrecs - true to retrieve all records, false to retrieve
+ * only available DRAM
+ *
+ * Return value:
+ * 0 if ok
+ * CFE_ERR_NOMORE if idx is beyond the last entry
+ ********************************************************************* */
+
+int cfe_arena_enum(int idx,int *type,uint64_t *start,uint64_t *size,int allrecs)
+{
+ arena_node_t *node;
+ queue_t *qb;
+ arena_t *arena = &cfe_arena;
+
+
+ for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
+ qb = qb->q_next) {
+ node = (arena_node_t *) qb;
+
+ if (allrecs || (!allrecs && (node->an_type == MEMTYPE_DRAM_AVAILABLE))) {
+ if (idx == 0) {
+ *type = node->an_type;
+ *start = node->an_address;
+ *size = node->an_length;
+ return 0;
+ }
+ idx--;
+ }
+ }
+
+ return CFE_ERR_NOMORE;
+
+}
+
+/* *********************************************************************
+ * cfe_arena_loadcheck(start,size)
+ *
+ * Determine if the specified memory area is within the available
+ * DRAM. This is used while loading executables to be sure we
+ * don't trash the firmware.
+ *
+ * Input parameters:
+ * start - starting physical address
+ * size - size of requested region
+ *
+ * Return value:
+ * true - ok to copy memory here
+ * false - not ok, memory overlaps firmware
+ ********************************************************************* */
+
+int cfe_arena_loadcheck(uintptr_t start,unsigned int size)
+{
+ arena_node_t *node;
+ queue_t *qb;
+ arena_t *arena = &cfe_arena;
+
+ /*
+ * If the address is in our boot area, it's okay
+ * for it to be a virtual address.
+ */
+
+ if ((start >= BOOT_START_ADDRESS) &&
+ ((start+size) <= (BOOT_START_ADDRESS+BOOT_AREA_SIZE))) {
+ return TRUE;
+ }
+
+ /*
+ * Otherwise, make a physical address.
+ */
+
+ start = PHYSADDR(start);
+
+ /*
+ * Because all of the arena nodes of the same type are
+ * coalesced together, all we need to do is determine if the
+ * requested region is entirely within an arena node,
+ * so there's no need to look for things that span nodes.
+ */
+
+ for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
+ qb = qb->q_next) {
+ node = (arena_node_t *) qb;
+
+ /* If the memory is available, the region is OK. */
+
+ if ((start >= node->an_address) &&
+ ((start+size) <= (node->an_address+node->an_length)) &&
+ (node->an_type == MEMTYPE_DRAM_AVAILABLE)) {
+ return TRUE;
+ }
+ }
+
+ /*
+ * Otherwise, it's not. We could go through the arena again and
+ * look for regions of other types that intersect the requested
+ * region, to get a more detailed error, but this'll do.
+ */
+
+ return FALSE;
+
+}
+
diff --git a/cfe/cfe/main/cfe_rawfs.c b/cfe/cfe/main/cfe_rawfs.c
new file mode 100644
index 0000000..4c29349
--- /dev/null
+++ b/cfe/cfe/main/cfe_rawfs.c
@@ -0,0 +1,293 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * "Raw" file system File: cfe_rawfs.c
+ *
+ * This filesystem dispatch is used to read files directly
+ * from a block device. For example, you can 'dd' an elf
+ * file directly onto a disk or flash card and then run
+ * it using this module.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_console.h"
+
+#include "cfe.h"
+
+/* *********************************************************************
+ * RAW context
+ ********************************************************************* */
+
+/*
+ * File system context - describes overall file system info,
+ * such as the handle to the underlying device.
+ */
+
+typedef struct raw_fsctx_s {
+ int raw_dev;
+ int raw_isconsole;
+ int raw_refcnt;
+} raw_fsctx_t;
+
+/*
+ * File context - describes an open file on the file system.
+ * For raw devices, this is pretty meaningless, but we do
+ * keep track of where we are.
+ */
+
+typedef struct raw_file_s {
+ raw_fsctx_t *raw_fsctx;
+ int raw_fileoffset;
+ int raw_baseoffset; /* starting offset of raw "file" */
+ int raw_length; /* length of file, -1 for whole device */
+} raw_file_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int raw_fileop_init(void **fsctx,void *devicename);
+static int raw_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int raw_fileop_read(void *ref,uint8_t *buf,int len);
+static int raw_fileop_write(void *ref,uint8_t *buf,int len);
+static int raw_fileop_seek(void *ref,int offset,int how);
+static void raw_fileop_close(void *ref);
+static void raw_fileop_uninit(void *fsctx);
+
+/* *********************************************************************
+ * RAW fileio dispatch table
+ ********************************************************************* */
+
+const fileio_dispatch_t raw_fileops = {
+ "raw",
+ 0,
+ raw_fileop_init,
+ raw_fileop_open,
+ raw_fileop_read,
+ raw_fileop_write,
+ raw_fileop_seek,
+ raw_fileop_close,
+ raw_fileop_uninit
+};
+
+static int raw_fileop_init(void **newfsctx,void *dev)
+{
+ raw_fsctx_t *fsctx;
+ char *devicename = (char *) dev;
+
+ *newfsctx = NULL;
+
+ fsctx = KMALLOC(sizeof(raw_fsctx_t),0);
+ if (!fsctx) {
+ return CFE_ERR_NOMEM;
+ }
+
+ if (strcmp(devicename,console_name) == 0) {
+ fsctx->raw_dev = console_handle;
+ fsctx->raw_isconsole = TRUE;
+ }
+ else {
+ fsctx->raw_dev = cfe_open(devicename);
+ fsctx->raw_isconsole = FALSE;
+ }
+
+ fsctx->raw_refcnt = 0;
+
+ if (fsctx->raw_dev >= 0) {
+ *newfsctx = fsctx;
+ return 0;
+ }
+
+ KFREE(fsctx);
+
+ return CFE_ERR_FILENOTFOUND;
+}
+
+static int raw_fileop_open(void **ref,void *fsctx_arg,char *filename,int mode)
+{
+ raw_fsctx_t *fsctx;
+ raw_file_t *file;
+ char temp[100];
+ char *len;
+
+ if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ fsctx = (raw_fsctx_t *) fsctx_arg;
+
+ file = KMALLOC(sizeof(raw_file_t),0);
+ if (!file) {
+ return CFE_ERR_NOMEM;
+ }
+
+ file->raw_fileoffset = 0;
+ file->raw_fsctx = fsctx;
+
+ /* Assume the whole device. */
+ file->raw_baseoffset = 0;
+ file->raw_length = -1;
+
+ /*
+ * If a filename was specified, it will be in the form
+ * offset,length - for example, 0x10000,0x200
+ * Parse this into two pieces and set up our internal
+ * file extent information. you can use either decimal
+ * or "0x" notation.
+ */
+ if (filename) {
+ lib_trimleading(filename);
+ strncpy(temp,filename,sizeof(temp));
+ len = strchr(temp,',');
+ if (len) *len++ = '\0';
+ if (temp[0]) {
+ file->raw_baseoffset = lib_atoi(temp);
+ }
+ if (len) {
+ file->raw_length = lib_atoi(len);
+ }
+ }
+
+ fsctx->raw_refcnt++;
+
+ *ref = file;
+ return 0;
+}
+
+static int raw_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ raw_file_t *file = (raw_file_t *) ref;
+ int res;
+
+ /*
+ * Bound the length based on our "file length" if one
+ * was specified.
+ */
+
+ if (file->raw_length >= 0) {
+ if ((file->raw_length - file->raw_fileoffset) < len) {
+ len = file->raw_length - file->raw_fileoffset;
+ }
+ }
+
+ if (len == 0) return 0;
+
+ /*
+ * Read the data, adding in the base address.
+ */
+
+ res = cfe_readblk(file->raw_fsctx->raw_dev,
+ file->raw_baseoffset + file->raw_fileoffset,
+ buf,len);
+
+ if (res > 0) {
+ file->raw_fileoffset += res;
+ }
+
+ return res;
+}
+
+static int raw_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ return CFE_ERR_UNSUPPORTED;
+}
+
+static int raw_fileop_seek(void *ref,int offset,int how)
+{
+ raw_file_t *file = (raw_file_t *) ref;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ file->raw_fileoffset = offset;
+ break;
+ case FILE_SEEK_CURRENT:
+ file->raw_fileoffset += offset;
+ if (file->raw_fileoffset < 0) file->raw_fileoffset = 0;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Make sure we don't attempt to seek past the end of the file.
+ */
+
+ if (file->raw_length >= 0) {
+ if (file->raw_fileoffset > file->raw_length) {
+ file->raw_fileoffset = file->raw_length;
+ }
+ }
+
+ return file->raw_fileoffset;
+}
+
+
+static void raw_fileop_close(void *ref)
+{
+ raw_file_t *file = (raw_file_t *) ref;
+
+ file->raw_fsctx->raw_refcnt--;
+
+ KFREE(file);
+}
+
+static void raw_fileop_uninit(void *fsctx_arg)
+{
+ raw_fsctx_t *fsctx = (raw_fsctx_t *) fsctx_arg;
+
+ if (fsctx->raw_refcnt) {
+ xprintf("raw_fileop_uninit: warning: refcnt not zero\n");
+ }
+
+ if (fsctx->raw_isconsole == FALSE) {
+ cfe_close(fsctx->raw_dev);
+ }
+
+ KFREE(fsctx);
+}
diff --git a/cfe/cfe/main/cfe_savedata.c b/cfe/cfe/main/cfe_savedata.c
new file mode 100644
index 0000000..e1d27c4
--- /dev/null
+++ b/cfe/cfe/main/cfe_savedata.c
@@ -0,0 +1,123 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Data Save routine File: cfe_savedata.c
+ *
+ * This module is used for dumping memory to an output device
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe.h"
+#include "cfe_fileops.h"
+
+#include "cfe_loader.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+/* *********************************************************************
+ * cfe_savedata(fsname,filename,start,end)
+ *
+ * Write memory contents to the specified device
+ *
+ * Input parameters:
+ * fsname - name of file system
+ * filename - name of file within file system
+ * start - starting address (pointer)
+ * end - ending address (pointer)
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+int cfe_savedata(char *fsname,char *devname,char *filename,uint8_t *start,uint8_t *end)
+{
+ int res;
+ fileio_ctx_t *fsctx;
+ void *ref;
+
+ /*
+ * Create a file system context
+ */
+
+ res = fs_init(fsname,&fsctx,devname);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Open the device
+ */
+
+ res = fs_open(fsctx,&ref,filename,FILE_MODE_WRITE);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ /*
+ * Write the data
+ */
+
+ res = fs_write(fsctx,ref,start,end-start);
+
+ /*
+ * Close
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ return res;
+
+}
+
diff --git a/cfe/cfe/main/cfe_timer.c b/cfe/cfe/main/cfe_timer.c
new file mode 100644
index 0000000..2b8a0fc
--- /dev/null
+++ b/cfe/cfe/main/cfe_timer.c
@@ -0,0 +1,286 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Timer routines File: cfe_timer.c
+ *
+ * This module contains routines to keep track of the system time,.
+ * Since we don't have any interrupts in the firmware, even the
+ * timer is polled. The timer must be called often enough
+ * to prevent missing the overflow of the CP0 COUNT
+ * register, approximately 2 billion cycles (half the count)
+ *
+ * Be sure to use the POLL() macro each time you enter a loop
+ * where you are waiting for some I/O event to occur or
+ * are waiting for time to elapse.
+ *
+ * It is *not* a time-of-year clock. The timer is only used
+ * for timing I/O events.
+ *
+ * Internally, time is maintained in units of "CLOCKSPERTICK",
+ * which should be about tenths of seconds.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+
+#include "cfe.h"
+
+#include "bsp_config.h"
+#include "cpu_config.h"
+
+/* Foxconn add start by Jenny Zhao, 07/02/2008*/
+#include "boardparms.h"
+#include "bcm63xx_util.h"
+#include "tftpd.h"
+/* Foxconn add end by Jenny Zhao, 07/02/2008*/
+
+#ifndef CFG_CPU_SPEED
+#define CFG_CPU_SPEED 500000 /* CPU speed in Hz */
+#endif
+
+#ifndef CPUCFG_CYCLESPERCPUTICK
+#define CPUCFG_CYCLESPERCPUTICK 1 /* CPU clock ticks per CP0 COUNT */
+#endif
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern int32_t _getticks(void); /* return value of CP0 COUNT */
+
+/* *********************************************************************
+ * Data
+ ********************************************************************* */
+
+volatile int64_t cfe_ticks; /* current system time */
+
+int cfe_cpu_speed = CFG_CPU_SPEED; /* CPU speed in clocks/second */
+
+static unsigned int cfe_clocks_per_usec;
+static unsigned int cfe_clocks_per_tick;
+
+static int32_t cfe_oldcount; /* For keeping track of ticks */
+static int32_t cfe_remticks;
+static int cfe_timer_initflg = 0;
+
+/*
+ * C0_COUNT clocks per microsecond and per tick. Some CPUs tick CP0
+ * every 'n' cycles, that's what CPUCFG_CYCLESPERCPUTICK is for. */
+#define CFE_CLOCKSPERUSEC (cfe_cpu_speed/1000000/(CPUCFG_CYCLESPERCPUTICK))
+#define CFE_CLOCKSPERTICK (cfe_cpu_speed/(CFE_HZ)/(CPUCFG_CYCLESPERCPUTICK))
+
+/* Foxconn add start by Jenny Zhao, 07/02/2008*/
+extern int ui_docommands(char *str);
+
+extern int g_tftp_upgrade_success;
+extern int nmrp_server_detected;
+
+//extern int g_reboot;
+///* Foxconn add end by Jenny Zhao, 07/02/2008*/
+
+/* *********************************************************************
+ * cfe_timer_task()
+ *
+ * This routine is called as part of normal device polling to
+ * update the system time. We read the CP0 COUNT register,
+ * add the delta into our current time, convert to ticks,
+ * and keep track of the COUNT register overflow
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+static void cfe_timer_task(void *arg)
+{
+ int32_t count;
+ int32_t deltaticks;
+ int32_t clockspertick;
+
+ /* Foxconn add start by Jenny Zhao, 07/02/2008*/
+ static int64_t nmrp_previous_trigger_ticks = 0;
+ static int64_t tftp_previous_trigger_ticks = 0;
+ static int tftp_led_state = 0;
+ /* Foxconn add start by Jenny Zhao, 07/02/2008*/
+
+ clockspertick = CFE_CLOCKSPERTICK;
+
+ count = _getticks();
+
+ if (count >= cfe_oldcount) {
+ deltaticks = (count - cfe_oldcount) / clockspertick;
+ cfe_remticks += (count - cfe_oldcount) % clockspertick;
+ }
+ else {
+ deltaticks = (cfe_oldcount - count) / clockspertick;
+ cfe_remticks += (cfe_oldcount - count) % clockspertick;
+ }
+
+ cfe_ticks += deltaticks + (cfe_remticks / clockspertick);
+ cfe_remticks %= clockspertick;
+ cfe_oldcount = count;
+
+ /* Foxconn add start by Jenny Zhao, 07/02/2008*/
+ if(g_tftp_upgrade_success==1)
+ {
+ if((cfe_ticks - nmrp_previous_trigger_ticks) > 5) //500 ms
+ {
+ nmrp_previous_trigger_ticks = cfe_ticks;
+ nmrp_led_toggle();
+ }
+ }
+
+ /* Blink Power LED in tftpd mode */
+ if ( (get_tftpd_state() != TFTPD_STATE_OFF) && (nmrp_server_detected==0) )
+ {
+ if(tftp_led_state == 0) //led is off
+ {
+ if((cfe_ticks - tftp_previous_trigger_ticks) > 7) //700ms, spec. is 750ms
+ {
+ tftp_led_state = 1;
+ power_led_toggle(tftp_led_state);
+ tftp_previous_trigger_ticks = cfe_ticks;
+ }
+ }
+ else // led is currently on
+ {
+ if((cfe_ticks - tftp_previous_trigger_ticks) > 3) //300ms, spec. is 250ms
+ {
+ tftp_led_state = 0;
+ power_led_toggle(tftp_led_state);
+ tftp_previous_trigger_ticks = cfe_ticks;
+ }
+ }
+ }
+ /* Foxconn add end by Jenny Zhao, 07/02/2008*/
+}
+
+
+/* *********************************************************************
+ * cfe_timer_init()
+ *
+ * Initialize the timer module.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_timer_init(void)
+{
+ cfe_clocks_per_tick = CFE_CLOCKSPERTICK;
+ cfe_clocks_per_usec = CFE_CLOCKSPERUSEC;
+ if (cfe_clocks_per_usec == 0)
+ cfe_clocks_per_usec = 1; /* for the simulator */
+
+ cfe_oldcount = _getticks(); /* get current COUNT register */
+ cfe_ticks = 0;
+
+ if (!cfe_timer_initflg) {
+ cfe_bg_add(cfe_timer_task,NULL); /* add task for background polling */
+ cfe_timer_initflg = 1;
+ }
+}
+
+
+/* *********************************************************************
+ * cfe_sleep(ticks)
+ *
+ * Sleep for 'ticks' ticks. Background tasks are processed while
+ * we wait.
+ *
+ * Input parameters:
+ * ticks - number of ticks to sleep (note: *not* clocks!)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_sleep(int ticks)
+{
+ int64_t timer;
+
+ TIMER_SET(timer,ticks);
+ while (!TIMER_EXPIRED(timer)) {
+ POLL();
+ }
+}
+
+
+
+/* *********************************************************************
+ * cfe_usleep(usec)
+ *
+ * Sleep for approximately the specified number of microseconds.
+ *
+ * Input parameters:
+ * usec - number of microseconds to wait
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_usleep(int usec)
+{
+ uint32_t newcount;
+ uint32_t now;
+
+ /* XXX fix the wrap problem */
+
+ now = _getticks();
+ newcount = now + usec*cfe_clocks_per_usec;
+
+ if (newcount < now) /* wait for wraparound */
+ while (_getticks() > now)
+ ;
+
+
+ while (_getticks() < newcount)
+ ;
+}
diff --git a/cfe/cfe/main/cfe_version.mk b/cfe/cfe/main/cfe_version.mk
new file mode 100755
index 0000000..653cbf9
--- /dev/null
+++ b/cfe/cfe/main/cfe_version.mk
@@ -0,0 +1,12 @@
+
+#
+# CFE's version number
+# Warning: Don't put spaces on either side of the equal signs
+# Put just the version number in here. This file is sourced
+# like a shell script in some cases!
+#
+
+CFE_VER_MAJ=1
+CFE_VER_MIN=0
+CFE_VER_ECO=37
+
diff --git a/cfe/cfe/main/cfe_xreq.c b/cfe/cfe/main/cfe_xreq.c
new file mode 100644
index 0000000..d12b1f2
--- /dev/null
+++ b/cfe/cfe/main/cfe_xreq.c
@@ -0,0 +1,346 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB dispatcher File: cfe_xreq.c
+ *
+ * This routine is the main API dispatch for CFE. User API
+ * calls, via the ROM entry point, get dispatched to routines
+ * in this module.
+ *
+ * This module looks similar to cfe_iocb_dispatch - it is different
+ * in that the data structure used, cfe_xiocb_t, uses fixed
+ * size field members (specifically, all 64-bits) no matter how
+ * the firmware is compiled. This ensures a consistent API
+ * interface on any implementation. When you call CFE
+ * from another program, the entry vector comes here first.
+ *
+ * Should the normal cfe_iocb interface change, this one should
+ * be kept the same for backward compatibility reasons.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "bsp_config.h"
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_xiocb.h"
+#if CFG_VENDOR_EXTENSIONS
+#include "cfe_vendor_iocb.h"
+#include "cfe_vendor_xiocb.h"
+#endif
+#include "cfe_error.h"
+#include "cfe_device.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+#include "env_subr.h"
+#include "cfe.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/* enum values for various plist types */
+
+#define PLBUF 1 /* iocb_buffer_t */
+#define PLCPU 2 /* iocb_cpuctl_t */
+#define PLMEM 3 /* iocb_meminfo_t */
+#define PLENV 4 /* iocb_envbuf_t */
+#define PLINP 5 /* iocb_inpstat_t */
+#define PLTIM 6 /* iocb_time_t */
+#define PLINF 7 /* iocb_fwinfo_t */
+#define PLEXIT 8 /* iocb_exitstat_t */
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+struct cfe_xcmd_dispatch_s {
+ int xplistsize;
+ int iplistsize;
+ int plisttype;
+};
+
+
+/* *********************************************************************
+ * Command conversion table
+ * This table contains useful information for converting
+ * iocbs to xiocbs.
+ ********************************************************************* */
+
+const static struct cfe_xcmd_dispatch_s cfe_xcmd_dispatch_table[CFE_CMD_MAX] = {
+ {sizeof(xiocb_fwinfo_t), sizeof(iocb_fwinfo_t), PLINF}, /* 0 : CFE_CMD_FW_GETINFO */
+ {sizeof(xiocb_exitstat_t),sizeof(iocb_exitstat_t),PLEXIT}, /* 1 : CFE_CMD_FW_RESTART */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 2 : CFE_CMD_FW_BOOT */
+ {sizeof(xiocb_cpuctl_t), sizeof(iocb_cpuctl_t), PLCPU}, /* 3 : CFE_CMD_FW_CPUCTL */
+ {sizeof(xiocb_time_t), sizeof(iocb_time_t), PLTIM}, /* 4 : CFE_CMD_FW_GETTIME */
+ {sizeof(xiocb_meminfo_t),sizeof(iocb_meminfo_t),PLMEM}, /* 5 : CFE_CMD_FW_MEMENUM */
+ {0, 0, 0}, /* 6 : CFE_CMD_FW_FLUSHCACHE */
+ {-1, 0, 0}, /* 7 : */
+ {-1, 0, 0}, /* 8 : */
+ {0, 0, 0}, /* 9 : CFE_CMD_DEV_GETHANDLE */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 10 : CFE_CMD_DEV_ENUM */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 11 : CFE_CMD_DEV_OPEN_*/
+ {sizeof(xiocb_inpstat_t),sizeof(iocb_inpstat_t),PLINP}, /* 12 : CFE_CMD_DEV_INPSTAT */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 13 : CFE_CMD_DEV_READ */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 14 : CFE_CMD_DEV_WRITE */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 15 : CFE_CMD_DEV_IOCTL */
+ {0, 0, 0}, /* 16 : CFE_CMD_DEV_CLOSE */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 17 : CFE_CMD_DEV_GETINFO */
+ {-1, 0, 0}, /* 18 : */
+ {-1, 0, 0}, /* 19 : */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 20 : CFE_CMD_ENV_ENUM */
+ {-1, 0, 0}, /* 21 : */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 22 : CFE_CMD_ENV_GET */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 23 : CFE_CMD_ENV_SET */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 24 : CFE_CMD_ENV_DEL */
+ {-1, 0, 0}, /* 25 : */
+ {-1, 0, 0}, /* 26 : */
+ {-1, 0, 0}, /* 27 : */
+ {-1, 0, 0}, /* 28 : */
+ {-1, 0, 0}, /* 29 : */
+ {-1, 0, 0}, /* 30 : */
+ {-1, 0, 0} /* 31 : */
+};
+
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern int cfe_iocb_dispatch(cfe_iocb_t *iocb);
+cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb);
+#if CFG_VENDOR_EXTENSIONS
+extern cfe_int_t cfe_vendor_doxreq(cfe_vendor_xiocb_t *xiocb);
+#endif
+
+/* *********************************************************************
+ * cfe_doxreq(xiocb)
+ *
+ * Process an xiocb request. This routine converts an xiocb
+ * into an iocb, calls the IOCB dispatcher, converts the results
+ * back into the xiocb, and returns.
+ *
+ * Input parameters:
+ * xiocb - pointer to user xiocb
+ *
+ * Return value:
+ * command status, <0 if error occured
+ ********************************************************************* */
+
+cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb)
+{
+ const struct cfe_xcmd_dispatch_s *disp;
+ cfe_iocb_t iiocb;
+ cfe_int_t res;
+
+ /*
+ * Call out to customer-specific IOCBs. Customers may choose
+ * to implement their own XIOCBs directly, or go through their own
+ * translation layer (xiocb->iocb like CFE does) to insulate
+ * themselves from IOCB changes in the future.
+ */
+ if (xiocb->xiocb_fcode >= CFE_CMD_VENDOR_USE) {
+#if CFG_VENDOR_EXTENSIONS
+ return cfe_vendor_doxreq((cfe_vendor_xiocb_t *)xiocb);
+#else
+ return CFE_ERR_INV_COMMAND;
+#endif
+ }
+
+ /*
+ * Check for commands codes out of range
+ */
+
+ if ((xiocb->xiocb_fcode < 0) || (xiocb->xiocb_fcode >= CFE_CMD_MAX)) {
+ xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
+ return xiocb->xiocb_status;
+ }
+
+ /*
+ * Check for command codes in range but invalid
+ */
+
+ disp = &cfe_xcmd_dispatch_table[xiocb->xiocb_fcode];
+
+ if (disp->xplistsize < 0) {
+ xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
+ return xiocb->xiocb_status;
+ }
+
+ /*
+ * Check for invalid parameter list size
+ */
+
+ if (disp->xplistsize != xiocb->xiocb_psize) {
+ xiocb->xiocb_status = CFE_ERR_INV_PARAM;
+ return xiocb->xiocb_status;
+ }
+
+ /*
+ * Okay, copy parameters into the internal IOCB.
+ * First, the fixed header.
+ */
+
+ iiocb.iocb_fcode = (unsigned int) xiocb->xiocb_fcode;
+ iiocb.iocb_status = (int) xiocb->xiocb_status;
+ iiocb.iocb_handle = (int) xiocb->xiocb_handle;
+ iiocb.iocb_flags = (unsigned int) xiocb->xiocb_flags;
+ iiocb.iocb_psize = (unsigned int) disp->iplistsize;
+
+ /*
+ * Now the parameter list
+ */
+
+ switch (disp->plisttype) {
+ case PLBUF:
+ iiocb.plist.iocb_buffer.buf_offset = (cfe_offset_t) xiocb->plist.xiocb_buffer.buf_offset;
+ iiocb.plist.iocb_buffer.buf_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_buffer.buf_ptr;
+ iiocb.plist.iocb_buffer.buf_length = (unsigned int) xiocb->plist.xiocb_buffer.buf_length;
+ iiocb.plist.iocb_buffer.buf_retlen = (unsigned int) xiocb->plist.xiocb_buffer.buf_retlen;
+ iiocb.plist.iocb_buffer.buf_ioctlcmd = (unsigned int) xiocb->plist.xiocb_buffer.buf_ioctlcmd;
+ break;
+ case PLCPU:
+ iiocb.plist.iocb_cpuctl.cpu_number = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_number;
+ iiocb.plist.iocb_cpuctl.cpu_command = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_command;
+ iiocb.plist.iocb_cpuctl.start_addr = (unsigned long) xiocb->plist.xiocb_cpuctl.start_addr;
+ iiocb.plist.iocb_cpuctl.gp_val = (unsigned long) xiocb->plist.xiocb_cpuctl.gp_val;
+ iiocb.plist.iocb_cpuctl.sp_val = (unsigned long) xiocb->plist.xiocb_cpuctl.sp_val;
+ iiocb.plist.iocb_cpuctl.a1_val = (unsigned long) xiocb->plist.xiocb_cpuctl.a1_val;
+ break;
+ case PLMEM:
+ iiocb.plist.iocb_meminfo.mi_idx = (int) xiocb->plist.xiocb_meminfo.mi_idx;
+ iiocb.plist.iocb_meminfo.mi_type = (int) xiocb->plist.xiocb_meminfo.mi_type;
+ iiocb.plist.iocb_meminfo.mi_addr = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_addr;
+ iiocb.plist.iocb_meminfo.mi_size = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_size;
+ break;
+ case PLENV:
+ iiocb.plist.iocb_envbuf.enum_idx = (int) xiocb->plist.xiocb_envbuf.enum_idx;
+ iiocb.plist.iocb_envbuf.name_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.name_ptr;
+ iiocb.plist.iocb_envbuf.name_length = (int) xiocb->plist.xiocb_envbuf.name_length;
+ iiocb.plist.iocb_envbuf.val_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.val_ptr;
+ iiocb.plist.iocb_envbuf.val_length = (int) xiocb->plist.xiocb_envbuf.val_length;
+ break;
+ case PLINP:
+ iiocb.plist.iocb_inpstat.inp_status = (int) xiocb->plist.xiocb_inpstat.inp_status;
+ break;
+ case PLTIM:
+ iiocb.plist.iocb_time.ticks = (long long) xiocb->plist.xiocb_time.ticks;
+ break;
+ case PLINF:
+ break;
+ case PLEXIT:
+ iiocb.plist.iocb_exitstat.status = (long long) xiocb->plist.xiocb_exitstat.status;
+ break;
+ }
+
+ /*
+ * Do the internal function dispatch
+ */
+
+ res = (cfe_int_t) cfe_iocb_dispatch(&iiocb);
+
+ /*
+ * Now convert the parameter list members back
+ */
+
+ switch (disp->plisttype) {
+ case PLBUF:
+ xiocb->plist.xiocb_buffer.buf_offset = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_offset;
+ xiocb->plist.xiocb_buffer.buf_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_buffer.buf_ptr;
+ xiocb->plist.xiocb_buffer.buf_length = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_length;
+ xiocb->plist.xiocb_buffer.buf_retlen = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_retlen;
+ xiocb->plist.xiocb_buffer.buf_ioctlcmd = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_ioctlcmd;
+ break;
+ case PLCPU:
+ xiocb->plist.xiocb_cpuctl.cpu_number = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_number;
+ xiocb->plist.xiocb_cpuctl.cpu_command = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_command;
+ xiocb->plist.xiocb_cpuctl.start_addr = (cfe_uint_t) iiocb.plist.iocb_cpuctl.start_addr;
+ break;
+ case PLMEM:
+ xiocb->plist.xiocb_meminfo.mi_idx = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_idx;
+ xiocb->plist.xiocb_meminfo.mi_type = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_type;
+ xiocb->plist.xiocb_meminfo.mi_addr = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_addr;
+ xiocb->plist.xiocb_meminfo.mi_size = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_size;
+ break;
+ case PLENV:
+ xiocb->plist.xiocb_envbuf.enum_idx = (cfe_int_t) iiocb.plist.iocb_envbuf.enum_idx;
+ xiocb->plist.xiocb_envbuf.name_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.name_ptr;
+ xiocb->plist.xiocb_envbuf.name_length = (cfe_int_t) iiocb.plist.iocb_envbuf.name_length;
+ xiocb->plist.xiocb_envbuf.val_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.val_ptr;
+ xiocb->plist.xiocb_envbuf.val_length = (cfe_int_t) iiocb.plist.iocb_envbuf.val_length;
+ break;
+ case PLINP:
+ xiocb->plist.xiocb_inpstat.inp_status = (cfe_int_t) iiocb.plist.iocb_inpstat.inp_status;
+ break;
+ case PLTIM:
+ xiocb->plist.xiocb_time.ticks = (cfe_int_t) iiocb.plist.iocb_time.ticks;
+ break;
+ case PLINF:
+ xiocb->plist.xiocb_fwinfo.fwi_version = iiocb.plist.iocb_fwinfo.fwi_version;
+ xiocb->plist.xiocb_fwinfo.fwi_totalmem = iiocb.plist.iocb_fwinfo.fwi_totalmem;
+ xiocb->plist.xiocb_fwinfo.fwi_flags = iiocb.plist.iocb_fwinfo.fwi_flags;
+ xiocb->plist.xiocb_fwinfo.fwi_boardid = iiocb.plist.iocb_fwinfo.fwi_boardid;
+ xiocb->plist.xiocb_fwinfo.fwi_bootarea_va = iiocb.plist.iocb_fwinfo.fwi_bootarea_va;
+ xiocb->plist.xiocb_fwinfo.fwi_bootarea_pa = iiocb.plist.iocb_fwinfo.fwi_bootarea_pa;
+ xiocb->plist.xiocb_fwinfo.fwi_bootarea_size = iiocb.plist.iocb_fwinfo.fwi_bootarea_size;
+ xiocb->plist.xiocb_fwinfo.fwi_reserved1 = iiocb.plist.iocb_fwinfo.fwi_reserved1;
+ xiocb->plist.xiocb_fwinfo.fwi_reserved2 = iiocb.plist.iocb_fwinfo.fwi_reserved2;
+ xiocb->plist.xiocb_fwinfo.fwi_reserved3 = iiocb.plist.iocb_fwinfo.fwi_reserved3;
+ break;
+ case PLEXIT:
+ xiocb->plist.xiocb_exitstat.status = (cfe_int_t) iiocb.plist.iocb_exitstat.status;
+ break;
+ }
+
+ /*
+ * And the fixed header
+ */
+
+ xiocb->xiocb_status = (cfe_int_t) iiocb.iocb_status;
+ xiocb->xiocb_handle = (cfe_int_t) iiocb.iocb_handle;
+ xiocb->xiocb_flags = (cfe_uint_t) iiocb.iocb_flags;
+
+ return xiocb->xiocb_status;
+}
diff --git a/cfe/cfe/main/cfe_zlibfs.c b/cfe/cfe/main/cfe_zlibfs.c
new file mode 100644
index 0000000..7ad0847
--- /dev/null
+++ b/cfe/cfe/main/cfe_zlibfs.c
@@ -0,0 +1,453 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * "Compressed" file system File: cfe_zlibfs.c
+ *
+ * This is more of a filesystem "hook" than an actual file system.
+ * You can stick it on the front of the chain of file systems
+ * that CFE calls and it will route data read from the
+ * underlying filesystem through ZLIB before passing it up to the
+ * user.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#if CFG_ZLIB
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_console.h"
+
+#include "cfe.h"
+
+#include "zlib.h"
+
+/* *********************************************************************
+ * ZLIBFS context
+ ********************************************************************* */
+
+/*
+ * File system context - describes overall file system info,
+ * such as the handle to the underlying device.
+ */
+
+typedef struct zlibfs_fsctx_s {
+ void *zlibfsctx_subfsctx;
+ const fileio_dispatch_t *zlibfsctx_subops;
+ int zlibfsctx_refcnt;
+} zlibfs_fsctx_t;
+
+/*
+ * File context - describes an open file on the file system.
+ * For raw devices, this is pretty meaningless, but we do
+ * keep track of where we are.
+ */
+
+#define ZLIBFS_BUFSIZE 1024
+typedef struct zlibfs_file_s {
+ zlibfs_fsctx_t *zlibfs_fsctx;
+ int zlibfs_fileoffset;
+ void *zlibfs_subfile;
+ z_stream zlibfs_stream;
+ uint8_t *zlibfs_inbuf;
+ uint8_t *zlibfs_outbuf;
+ int zlibfs_outlen;
+ uint8_t *zlibfs_outptr;
+ int zlibfs_eofseen;
+} zlibfs_file_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int zlibfs_fileop_init(void **fsctx,void *ctx);
+static int zlibfs_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int zlibfs_fileop_read(void *ref,uint8_t *buf,int len);
+static int zlibfs_fileop_write(void *ref,uint8_t *buf,int len);
+static int zlibfs_fileop_seek(void *ref,int offset,int how);
+static void zlibfs_fileop_close(void *ref);
+static void zlibfs_fileop_uninit(void *fsctx);
+
+voidpf zcalloc(voidpf opaque,unsigned items, unsigned size);
+void zcfree(voidpf opaque,voidpf ptr);
+
+/* *********************************************************************
+ * ZLIB fileio dispatch table
+ ********************************************************************* */
+
+
+static uint8_t gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+const fileio_dispatch_t zlibfs_fileops = {
+ "z",
+ 0,
+ zlibfs_fileop_init,
+ zlibfs_fileop_open,
+ zlibfs_fileop_read,
+ zlibfs_fileop_write,
+ zlibfs_fileop_seek,
+ zlibfs_fileop_close,
+ zlibfs_fileop_uninit
+};
+
+/*
+ * Utility functions needed by the ZLIB routines
+ */
+voidpf zcalloc(voidpf opaque,unsigned items, unsigned size)
+{
+ void *ptr;
+
+ ptr = KMALLOC(items*size,0);
+ if (ptr) lib_memset(ptr,0,items*size);
+ return ptr;
+}
+
+void zcfree(voidpf opaque,voidpf ptr)
+{
+ KFREE(ptr);
+}
+
+
+static int zlibfs_fileop_init(void **newfsctx,void *curfsvoid)
+{
+ zlibfs_fsctx_t *fsctx;
+ fileio_ctx_t *curfsctx = (fileio_ctx_t *) curfsvoid;
+
+ *newfsctx = NULL;
+
+ fsctx = KMALLOC(sizeof(zlibfs_fsctx_t),0);
+ if (!fsctx) {
+ return CFE_ERR_NOMEM;
+ }
+
+ fsctx->zlibfsctx_refcnt = 0;
+ fsctx->zlibfsctx_subops = curfsctx->ops;
+ fsctx->zlibfsctx_subfsctx = curfsctx->fsctx;
+
+ *newfsctx = fsctx;
+
+ return 0;
+}
+
+
+static int get_byte(zlibfs_file_t *file,uint8_t *ch)
+{
+ int res;
+
+ res = BDREAD(file->zlibfs_fsctx->zlibfsctx_subops,
+ file->zlibfs_subfile,
+ ch,
+ 1);
+
+ return res;
+}
+
+
+static int check_header(zlibfs_file_t *file)
+{
+ int method; /* method byte */
+ int flags; /* flags byte */
+ uInt len;
+ uint8_t c;
+ int res;
+
+ /* Check the gzip magic header */
+ for (len = 0; len < 2; len++) {
+ res = get_byte(file,&c);
+ if (c != gz_magic[len]) {
+ return -1;
+ }
+ }
+
+ get_byte(file,&c); method = (int) c;
+ get_byte(file,&c); flags = (int) c;
+
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ return -1;
+ }
+
+ /* Discard time, xflags and OS code: */
+ for (len = 0; len < 6; len++) (void)get_byte(file,&c);
+
+ if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+ get_byte(file,&c);
+ len = (uInt) c;
+ get_byte(file,&c);
+ len += ((uInt)c)<<8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while ((len-- != 0) && (get_byte(file,&c) == 1)) ;
+ }
+ if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+ while ((get_byte(file,&c) == 1) && (c != 0)) ;
+ }
+ if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
+ while ((get_byte(file,&c) == 1) && (c != 0)) ;
+ }
+ if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte(file,&c);
+ }
+
+ return 0;
+}
+
+static int zlibfs_fileop_open(void **ref,void *fsctx_arg,char *filename,int mode)
+{
+ zlibfs_fsctx_t *fsctx;
+ zlibfs_file_t *file;
+ int err;
+
+ if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ fsctx = (zlibfs_fsctx_t *) fsctx_arg;
+
+ file = KMALLOC(sizeof(zlibfs_file_t),0);
+ if (!file) {
+ return CFE_ERR_NOMEM;
+ }
+
+ file->zlibfs_fileoffset = 0;
+ file->zlibfs_fsctx = fsctx;
+ file->zlibfs_inbuf = NULL;
+ file->zlibfs_outbuf = NULL;
+ file->zlibfs_eofseen = 0;
+
+ err = BDOPEN(fsctx->zlibfsctx_subops,&(file->zlibfs_subfile),
+ fsctx->zlibfsctx_subfsctx,filename);
+
+ if (err != 0) {
+ goto error2;
+ return err;
+ }
+
+ /* Open the zstream */
+
+ file->zlibfs_inbuf = KMALLOC(ZLIBFS_BUFSIZE,0);
+ file->zlibfs_outbuf = KMALLOC(ZLIBFS_BUFSIZE,0);
+
+ if (!file->zlibfs_inbuf || !file->zlibfs_outbuf) {
+ err = CFE_ERR_NOMEM;
+ goto error;
+ }
+
+ file->zlibfs_stream.next_in = NULL;
+ file->zlibfs_stream.avail_in = 0;
+ file->zlibfs_stream.next_out = file->zlibfs_outbuf;
+ file->zlibfs_stream.avail_out = ZLIBFS_BUFSIZE;
+ file->zlibfs_stream.zalloc = (alloc_func)0;
+ file->zlibfs_stream.zfree = (free_func)0;
+
+ file->zlibfs_outlen = 0;
+ file->zlibfs_outptr = file->zlibfs_outbuf;
+
+ err = inflateInit2(&(file->zlibfs_stream),-15);
+ if (err != Z_OK) {
+ err = CFE_ERR;
+ goto error;
+ }
+
+ check_header(file);
+
+ fsctx->zlibfsctx_refcnt++;
+
+ *ref = file;
+ return 0;
+
+error:
+ BDCLOSE(file->zlibfs_fsctx->zlibfsctx_subops,file->zlibfs_subfile);
+error2:
+ if (file->zlibfs_inbuf) KFREE(file->zlibfs_inbuf);
+ if (file->zlibfs_outbuf) KFREE(file->zlibfs_outbuf);
+ KFREE(file);
+ return err;
+}
+
+static int zlibfs_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ zlibfs_file_t *file = (zlibfs_file_t *) ref;
+ int res = 0;
+ int err;
+ int amtcopy;
+ int ttlcopy = 0;
+
+ if (len == 0) return 0;
+
+ while (len) {
+
+ /* Figure the amount to copy. This is the min of what we
+ have left to do and what is available. */
+ amtcopy = len;
+ if (amtcopy > file->zlibfs_outlen) {
+ amtcopy = file->zlibfs_outlen;
+ }
+
+ /* Copy the data. */
+
+ if (buf) {
+ memcpy(buf,file->zlibfs_outptr,amtcopy);
+ buf += amtcopy;
+ }
+
+ /* Update the pointers. */
+ file->zlibfs_outptr += amtcopy;
+ file->zlibfs_outlen -= amtcopy;
+ len -= amtcopy;
+ ttlcopy += amtcopy;
+
+ /* If we've eaten all of the output, reset and call inflate
+ again. */
+
+ if (file->zlibfs_outlen == 0) {
+ /* If no input data to decompress, get some more if we can. */
+ if (file->zlibfs_eofseen) break;
+ if (file->zlibfs_stream.avail_in == 0) {
+ res = BDREAD(file->zlibfs_fsctx->zlibfsctx_subops,
+ file->zlibfs_subfile,
+ file->zlibfs_inbuf,
+ ZLIBFS_BUFSIZE);
+ /* If at EOF or error, get out. */
+ if (res <= 0) break;
+ file->zlibfs_stream.next_in = file->zlibfs_inbuf;
+ file->zlibfs_stream.avail_in = res;
+ }
+
+ /* inflate the input data. */
+ file->zlibfs_stream.next_out = file->zlibfs_outbuf;
+ file->zlibfs_stream.avail_out = ZLIBFS_BUFSIZE;
+ file->zlibfs_outptr = file->zlibfs_outbuf;
+ err = inflate(&(file->zlibfs_stream),Z_SYNC_FLUSH);
+ if (err == Z_STREAM_END) {
+ /* We can get a partial buffer fill here. */
+ file->zlibfs_eofseen = 1;
+ }
+ else if (err != Z_OK) {
+ res = CFE_ERR;
+ break;
+ }
+ file->zlibfs_outlen = file->zlibfs_stream.next_out -
+ file->zlibfs_outptr;
+ }
+
+ }
+
+ file->zlibfs_fileoffset += ttlcopy;
+
+ return (res < 0) ? res : ttlcopy;
+}
+
+static int zlibfs_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ return CFE_ERR_UNSUPPORTED;
+}
+
+static int zlibfs_fileop_seek(void *ref,int offset,int how)
+{
+ zlibfs_file_t *file = (zlibfs_file_t *) ref;
+ int res;
+ int delta;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ delta = offset - file->zlibfs_fileoffset;
+ break;
+ case FILE_SEEK_CURRENT:
+ delta = offset;
+ break;
+ default:
+ return CFE_ERR_UNSUPPORTED;
+ break;
+ }
+
+ /* backward seeking not allowed on compressed streams */
+ if (delta < 0) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ res = zlibfs_fileop_read(ref,NULL,delta);
+
+ if (res < 0) return res;
+
+ return file->zlibfs_fileoffset;
+}
+
+
+static void zlibfs_fileop_close(void *ref)
+{
+ zlibfs_file_t *file = (zlibfs_file_t *) ref;
+
+ file->zlibfs_fsctx->zlibfsctx_refcnt--;
+
+ inflateEnd(&(file->zlibfs_stream));
+
+ BDCLOSE(file->zlibfs_fsctx->zlibfsctx_subops,file->zlibfs_subfile);
+
+ KFREE(file);
+}
+
+static void zlibfs_fileop_uninit(void *fsctx_arg)
+{
+ zlibfs_fsctx_t *fsctx = (zlibfs_fsctx_t *) fsctx_arg;
+
+ if (fsctx->zlibfsctx_refcnt) {
+ xprintf("zlibfs_fileop_uninit: warning: refcnt not zero\n");
+ }
+
+ BDUNINIT(fsctx->zlibfsctx_subops,fsctx->zlibfsctx_subfsctx);
+
+ KFREE(fsctx);
+}
+
+
+#endif
diff --git a/cfe/cfe/main/env_subr.c b/cfe/cfe/main/env_subr.c
new file mode 100644
index 0000000..5f12359
--- /dev/null
+++ b/cfe/cfe/main/env_subr.c
@@ -0,0 +1,474 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Environment variable subroutines File: env_subr.c
+ *
+ * This module contains routines to muck with environment variables
+ * (manage the list, read/write to nvram, etc.)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "env_subr.h"
+#include "nvram_subr.h"
+
+#include "cfe_error.h"
+#include "cfe.h"
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+typedef struct cfe_envvar_s {
+ queue_t qb;
+ int flags;
+ char *name;
+ char *value;
+ /* name and value go here */
+} cfe_envvar_t;
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+queue_t env_envvars = {&env_envvars,&env_envvars};
+extern unsigned int cfe_startflags;
+
+/* *********************************************************************
+ * env_findenv(name)
+ *
+ * Locate an environment variable in the in-memory list
+ *
+ * Input parameters:
+ * name - name of env var to find
+ *
+ * Return value:
+ * cfe_envvar_t pointer, or NULL if not found
+ ********************************************************************* */
+
+static cfe_envvar_t *env_findenv(const char *name)
+{
+ queue_t *qb;
+ cfe_envvar_t *env;
+
+ for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
+ env = (cfe_envvar_t *) qb;
+ if (strcmp(env->name,name) == 0) break;
+ }
+
+ if (qb == &env_envvars) return NULL;
+
+ return (cfe_envvar_t *) qb;
+
+}
+
+/* *********************************************************************
+ * env_enum(idx,name,namelen,val,vallen)
+ *
+ * Enumerate environment variables. This routine locates
+ * the nth environment variable and copies its name and value
+ * to user buffers.
+ *
+ * The namelen and vallen variables must be preinitialized to
+ * the maximum size of the output buffer.
+ *
+ * Input parameters:
+ * idx - variable index to find (starting with zero)
+ * name,namelen - name buffer and length
+ * val,vallen - value buffer and length
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int env_enum(int idx,char *name,int *namelen,char *val,int *vallen)
+{
+ queue_t *qb;
+ cfe_envvar_t *env;
+
+ for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
+ if (idx == 0) break;
+ idx--;
+ }
+
+ if (qb == &env_envvars) return CFE_ERR_ENVNOTFOUND;
+ env = (cfe_envvar_t *) qb;
+
+ *namelen = xstrncpy(name,env->name,*namelen);
+ *vallen = xstrncpy(val,env->value,*vallen);
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * env_envtype(name)
+ *
+ * Return the type of the environment variable
+ *
+ * Input parameters:
+ * name - name of environment variable
+ *
+ * Return value:
+ * flags, or <0 if error occured
+ ********************************************************************* */
+int env_envtype(const char *name)
+{
+ cfe_envvar_t *env;
+
+ env = env_findenv(name);
+
+ if (env) {
+ return env->flags;
+ }
+
+ return CFE_ERR_ENVNOTFOUND;
+}
+
+
+
+/* *********************************************************************
+ * env_delenv(name)
+ *
+ * Delete an environment variable
+ *
+ * Input parameters:
+ * name - environment variable to delete
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int env_delenv(const char *name)
+{
+ cfe_envvar_t *env;
+
+ env = env_findenv(name);
+
+ if (!env) return 0;
+
+ if (!(env->flags & ENV_FLG_READONLY)) {
+ q_dequeue((queue_t *) env);
+ KFREE(env);
+ return 0;
+ }
+
+ return CFE_ERR_ENVNOTFOUND;
+}
+
+/* *********************************************************************
+ * env_getenv(name)
+ *
+ * Retrieve the value of an environment variable
+ *
+ * Input parameters:
+ * name - name of environment variable to find
+ *
+ * Return value:
+ * value, or NULL if variable is not found
+ ********************************************************************* */
+
+char *env_getenv(const char *name)
+{
+ cfe_envvar_t *env;
+
+ env = env_findenv(name);
+
+ if (env) {
+ return env->value;
+ }
+
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * env_setenv(name,value,flags)
+ *
+ * Set the value of an environment variable
+ *
+ * Input parameters:
+ * name - name of variable
+ * value - value of variable
+ * flags - flags for variable (ENV_FLG_xxx)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int env_setenv(const char *name,char *value,int flags)
+{
+ cfe_envvar_t *env;
+ int namelen;
+
+ env = env_findenv(name);
+ if (env) {
+ if (!(flags & ENV_FLG_ADMIN)) {
+ if (env->flags & ENV_FLG_READONLY) return CFE_ERR_ENVREADONLY;
+ }
+ q_dequeue((queue_t *) env);
+ KFREE(env);
+ }
+
+ namelen = strlen(name);
+
+ env = KMALLOC(sizeof(cfe_envvar_t) + namelen + 1 + strlen(value) + 1,0);
+ if (!env) return CFE_ERR_NOMEM;
+
+ env->name = (char *) (env+1);
+ env->value = env->name + namelen + 1;
+ env->flags = (flags & ENV_FLG_MASK);
+
+ strcpy(env->name,name);
+ strcpy(env->value,value);
+
+ q_enqueue(&env_envvars,(queue_t *) env);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * env_load()
+ *
+ * Load the environment from the NVRAM device.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+
+int env_load(void)
+{
+ int size;
+ unsigned char *buffer;
+ unsigned char *ptr;
+ unsigned char *envval;
+ unsigned int reclen;
+ unsigned int rectype;
+ int offset;
+ int flg;
+ int retval = -1;
+ char valuestr[256];
+
+ /*
+ * If in 'safe mode', don't read the environment the first time.
+ */
+
+ if (cfe_startflags & CFE_INIT_SAFE) {
+ cfe_startflags &= ~CFE_INIT_SAFE;
+ return 0;
+ }
+
+ flg = nvram_open();
+ if (flg < 0) return flg;
+
+ size = nvram_getsize();
+ buffer = KMALLOC(size,0);
+
+ if (buffer == NULL) return CFE_ERR_NOMEM;
+
+ ptr = buffer;
+ offset = 0;
+
+ /* Read the record type and length */
+ if (nvram_read(ptr,offset,1) != 1) {
+ retval = CFE_ERR_IOERR;
+ goto error;
+ }
+
+ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
+
+ /* Adjust pointer for TLV type */
+ rectype = *(ptr);
+ offset++;
+ size--;
+
+ /*
+ * Read the length. It can be either 1 or 2 bytes
+ * depending on the code
+ */
+ if (rectype & ENV_LENGTH_8BITS) {
+ /* Read the record type and length - 8 bits */
+ if (nvram_read(ptr,offset,1) != 1) {
+ retval = CFE_ERR_IOERR;
+ goto error;
+ }
+ reclen = *(ptr);
+ size--;
+ offset++;
+ }
+ else {
+ /* Read the record type and length - 16 bits, MSB first */
+ if (nvram_read(ptr,offset,2) != 2) {
+ retval = CFE_ERR_IOERR;
+ goto error;
+ }
+ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
+ size -= 2;
+ offset += 2;
+ }
+
+ if (reclen > size) break; /* should not happen, bad NVRAM */
+
+ switch (rectype) {
+ case ENV_TLV_TYPE_ENV:
+ /* Read the TLV data */
+ if (nvram_read(ptr,offset,reclen) != reclen) goto error;
+ flg = *ptr++;
+ envval = (unsigned char *) strnchr(ptr,'=',(reclen-1));
+ if (envval) {
+ *envval++ = '\0';
+ memcpy(valuestr,envval,(reclen-1)-(envval-ptr));
+ valuestr[(reclen-1)-(envval-ptr)] = '\0';
+ env_setenv(ptr,valuestr,flg);
+ }
+ break;
+
+ default:
+ /* Unknown TLV type, skip it. */
+ break;
+ }
+
+ /*
+ * Advance to next TLV
+ */
+
+ size -= (int)reclen;
+ offset += reclen;
+
+ /* Read the next record type */
+ ptr = buffer;
+ if (nvram_read(ptr,offset,1) != 1) goto error;
+ }
+
+ retval = 0; /* success! */
+
+error:
+ KFREE(buffer);
+ nvram_close();
+
+ return retval;
+
+}
+
+
+/* *********************************************************************
+ * env_save()
+ *
+ * Write the environment to the NVRAM device.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int env_save(void)
+{
+ int size;
+ unsigned char *buffer;
+ unsigned char *buffer_end;
+ unsigned char *ptr;
+ queue_t *qb;
+ cfe_envvar_t *env;
+ int namelen;
+ int valuelen;
+ int flg;
+
+ flg = nvram_open();
+ if (flg < 0) return flg;
+
+ nvram_erase();
+
+ size = nvram_getsize();
+ buffer = KMALLOC(size,0);
+
+ if (buffer == NULL) return CFE_ERR_NOMEM;
+
+ buffer_end = buffer + size;
+
+ ptr = buffer;
+
+ for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
+ env = (cfe_envvar_t *) qb;
+
+ if (env->flags & (ENV_FLG_BUILTIN)) continue;
+
+ namelen = strlen(env->name);
+ valuelen = strlen(env->value);
+
+ if ((ptr + 2 + namelen + valuelen + 1 + 1 + 1) > buffer_end) break;
+
+ *ptr++ = ENV_TLV_TYPE_ENV; /* TLV record type */
+ *ptr++ = (namelen + valuelen + 1 + 1); /* TLV record length */
+
+ *ptr++ = (unsigned char)env->flags;
+ memcpy(ptr,env->name,namelen); /* TLV record data */
+ ptr += namelen;
+ *ptr++ = '=';
+ memcpy(ptr,env->value,valuelen);
+ ptr += valuelen;
+
+ }
+
+ *ptr++ = ENV_TLV_TYPE_END;
+
+ size = nvram_write(buffer,0,ptr-buffer);
+
+ KFREE(buffer);
+
+ nvram_close();
+
+ return (size == (ptr-buffer)) ? 0 : CFE_ERR_IOERR;
+}
diff --git a/cfe/cfe/main/nvram_subr.c b/cfe/cfe/main/nvram_subr.c
new file mode 100644
index 0000000..2c44bca
--- /dev/null
+++ b/cfe/cfe/main/nvram_subr.c
@@ -0,0 +1,300 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * NVRAM subroutines File: nvram_subr.c
+ *
+ * High-level routines to read/write the NVRAM device.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_ioctl.h"
+
+#include "cfe_error.h"
+#include "env_subr.h"
+#include "nvram_subr.h"
+#include "cfe.h"
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+static int nvram_handle = -1;
+static nvram_info_t nvram_info;
+static char *nvram_devname = NULL;
+
+/* *********************************************************************
+ * nvram_getinfo(info)
+ *
+ * Obtain information about the NVRAM device from the device
+ * driver. A flash device might only dedicate a single sector
+ * to the environment, so we need to ask the driver first.
+ *
+ * Input parameters:
+ * info - nvram info
+ *
+ * Return value:
+ * 0 if ok
+ * <0 = error code
+ ********************************************************************* */
+
+static int nvram_getinfo(nvram_info_t *info)
+{
+ int retlen;
+
+ if (nvram_handle == -1) return -1;
+
+ cfe_ioctl(nvram_handle,IOCTL_NVRAM_UNLOCK,NULL,0,NULL,0);
+
+ if (cfe_ioctl(nvram_handle,IOCTL_NVRAM_GETINFO,
+ (unsigned char *) info,
+ sizeof(nvram_info_t),
+ &retlen,0) != 0) {
+ return -1;
+ }
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * nvram_open()
+ *
+ * Open the default NVRAM device and get the information from the
+ * device driver.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int nvram_open(void)
+{
+ if (nvram_handle != -1) {
+ nvram_close();
+ }
+
+ if (nvram_devname == NULL) {
+ return CFE_ERR_DEVNOTFOUND;
+ }
+
+ nvram_handle = cfe_open(nvram_devname);
+
+ if (nvram_handle < 0) {
+ return CFE_ERR_DEVNOTFOUND;
+ }
+
+ if (nvram_getinfo(&nvram_info) < 0) {
+ nvram_close();
+ return CFE_ERR_IOERR;
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * nvram_close()
+ *
+ * Close the NVRAM device
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+int nvram_close(void)
+{
+ if (nvram_handle != -1) {
+ cfe_close(nvram_handle);
+ nvram_handle = -1;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * nvram_getsize()
+ *
+ * Return the total size of the NVRAM device. Note that
+ * this is the total size that is used for the NVRAM functions,
+ * not the size of the underlying media.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * size. <0 if error
+ ********************************************************************* */
+
+int nvram_getsize(void)
+{
+ if (nvram_handle < 0) return 0;
+ return nvram_info.nvram_size;
+}
+
+
+/* *********************************************************************
+ * nvram_read(buffer,offset,length)
+ *
+ * Read data from the NVRAM device
+ *
+ * Input parameters:
+ * buffer - destination buffer
+ * offset - offset of data to read
+ * length - number of bytes to read
+ *
+ * Return value:
+ * number of bytes read, or <0 if error occured
+ ********************************************************************* */
+int nvram_read(unsigned char *buffer,int offset,int length)
+{
+ if (nvram_handle == -1) return -1;
+
+ return cfe_readblk(nvram_handle,
+ (cfe_offset_t) (offset+nvram_info.nvram_offset),
+ buffer,
+ length);
+}
+
+/* *********************************************************************
+ * nvram_write(buffer,offset,length)
+ *
+ * Write data to the NVRAM device
+ *
+ * Input parameters:
+ * buffer - source buffer
+ * offset - offset of data to write
+ * length - number of bytes to write
+ *
+ * Return value:
+ * number of bytes written, or -1 if error occured
+ ********************************************************************* */
+int nvram_write(unsigned char *buffer,int offset,int length)
+{
+ if (nvram_handle == -1) return -1;
+
+ return cfe_writeblk(nvram_handle,
+ (cfe_offset_t) (offset+nvram_info.nvram_offset),
+ buffer,
+ length);
+}
+
+
+/* *********************************************************************
+ * nvram_erase()
+ *
+ * Erase the NVRAM device. Not all devices need to be erased,
+ * but flash memory does.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int nvram_erase(void)
+{
+ int retlen;
+
+ if (nvram_handle < 0) {
+ return -1;
+ }
+
+ if (nvram_info.nvram_eraseflg == FALSE) return 0;
+
+ if (cfe_ioctl(nvram_handle,IOCTL_NVRAM_ERASE,
+ (unsigned char *) &nvram_info,
+ sizeof(nvram_info_t),
+ &retlen,0) != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * cfe_set_envdevice(name)
+ *
+ * Set the environment NVRAM device name
+ *
+ * Input parameters:
+ * name - name of device to use for NVRAM
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int cfe_set_envdevice(char *name)
+{
+ int res;
+
+ nvram_devname = strdup(name);
+
+ res = nvram_open();
+
+ if (res != 0) {
+ xprintf("!! Could not open NVRAM device %s\n",nvram_devname);
+ return res;
+ }
+
+ nvram_close();
+
+ res = env_load();
+
+ return res;
+}
diff --git a/cfe/cfe/main/nvram_subr.h b/cfe/cfe/main/nvram_subr.h
new file mode 100644
index 0000000..f614ec2
--- /dev/null
+++ b/cfe/cfe/main/nvram_subr.h
@@ -0,0 +1,54 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * NVRAM prototypes File: nvram_subr.h
+ *
+ * Prototypes for NVRAM routines.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+int nvram_getsize(void);
+int nvram_read(unsigned char *buffer,int,int);
+int nvram_write(unsigned char *buffer,int,int);
+int nvram_open(void);
+int nvram_close(void);
+int nvram_erase(void);
+