diff options
Diffstat (limited to 'cfe/cfe/main/cfe_rawfs.c')
-rw-r--r-- | cfe/cfe/main/cfe_rawfs.c | 293 |
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); +} |