summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/main/cfe_rawfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/main/cfe_rawfs.c')
-rw-r--r--cfe/cfe/main/cfe_rawfs.c293
1 files changed, 293 insertions, 0 deletions
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);
+}