2009-06-12 Joel Sherrill <joel.sherrill@OARcorp.com>

* umon/README, umon/cli.h, umon/monlib.c, umon/monlib.h, umon/tfs.h,
	umon/tfsDriver.c, umon/umonrtemsglue.c: New files.
This commit is contained in:
Joel Sherrill
2009-06-12 17:20:42 +00:00
parent c0ae2676b5
commit ba6f12b7e4
8 changed files with 2504 additions and 0 deletions

View File

@@ -1,3 +1,8 @@
2009-06-12 Joel Sherrill <joel.sherrill@OARcorp.com>
* umon/README, umon/cli.h, umon/monlib.c, umon/monlib.h, umon/tfs.h,
umon/tfsDriver.c, umon/umonrtemsglue.c: New files.
2009-05-27 Sebastian Huber <sebastian.huber@embedded-brains.de> 2009-05-27 Sebastian Huber <sebastian.huber@embedded-brains.de>
* tod.h, tod.c: Update for new RTC driver interface. * tod.h, tod.c: Update for new RTC driver interface.

View File

@@ -0,0 +1,47 @@
#
# $Id$
#
This directory contains support for utilitizing MicroMonitor
(http://www.umonfw.com/) capabilities from within an RTEMS
application. This directory contiains:
+ "MonLib" functionality as documented in the MicroMonitor
User's Manual.
+ TFS filesystem which makes the MicroMonitor TFS filesystem
available under RTEMS as a regular filesystem.
Usage
=====
For any of this functionality to work, the application is
responsible for connecting the library to the monitor.
This is done by calling rtems_umon_connect() early in the
application. This routine assumes that the BSP has provided
the routine rtems_bsp_get_umon_monptr() which returns the
value referred to as MONCOMPTR by MicroMonitor.
To use the TFS filesystem, it is necessary to mount it
by calling the rtems_initialize_tfs_filesystem() routine
and providing it the name of the mount point directory.
CONFIGURATION
=============
The TFS filesystem uses a single Classic API Semaphore.
The monlib functionality will eventually also use a single
Classic API Semaphore.
STATUS
======
+ Limited testing -- especially of TFS RTEMS filesystem.
+ monlib is NOT currently protected by a mutex.
SOURCE ORIGIN
=============
Some of the files in this directory are included in the
MicroMonitor distribution and may need to be updated
in the future.
12 June 2009: Source is from umon 1.17

View File

@@ -0,0 +1,123 @@
/* cli.h:
* Header file for Command Line Interface related stuff.
*
* General notice:
* This code is part of a boot-monitor package developed as a generic base
* platform for embedded system designs. As such, it is likely to be
* distributed to various projects beyond the control of the original
* author. Please notify the author of any enhancements made or bugs found
* so that all may benefit from the changes. In addition, notification back
* to the author will allow the new user to pick up changes that may have
* been made by other users after this version of the code was distributed.
*
* Note1: the majority of this code was edited with 4-space tabs.
* Note2: as more and more contributions are accepted, the term "author"
* is becoming a mis-representation of credit.
*
* Original author: Ed Sutter
* Email: esutter@lucent.com
* Phone: 908-582-2351
*/
#ifndef _cli_h
#define _cli_h
#ifdef __cplusplus
extern "C" {
#endif
/* Command table structure used by the monitor:
*/
struct monCommand {
char *name; /* Name of command seen by user. */
int (*func)(int,char **); /* Called when command is invoked. */
char **helptxt; /* Help text (see notes below). */
long flags; /* Single-bit flags for various uses */
/* (see the CMDFLAG_XXX macros). */
};
#ifdef __cplusplus
}
#endif
/* Bits currently assigned to command flags used in the monCommand
* structure...
*/
#define CMDFLAG_NOMONRC 1
/* Maximum size of a command line:
*/
#ifndef CMDLINESIZE
#define CMDLINESIZE 128
#endif
/* Maximum number of arguments in a command line:
*/
#define ARGCNT 24
/* Definitions for docommand() return values:
*
* Note that the CMD_SUCCESS, CMD_FAILURE and CMD_PARAM_ERROR are return
* values used by the local command code also. The remaining errors
* (CMD_LINE_ERROR, CMD_ULVL_DENIED and CMD_NOT_FOUND) are used only by
# the docommand() function.
*
* CMD_SUCCESS:
* Everything worked ok.
* CMD_FAILURE:
* Command parameters were valid, but command itself failed for some other
* reason. The docommand() function does not print a message here, it
* is assumed that the error message was printed by the local function.
* CMD_PARAM_ERROR:
* Command line did not parse properly. Control was passed to a
* local command function, but argument syntax caused it to choke.
* In this case docommand() will print out the generic CLI syntax error
* message.
* CMD_LINE_ERROR:
* Command line itself was invalid. Too many args, invalid shell var
* syntax, etc.. Somekind of command line error prior to checking for
* the command name-to-function match.
* CMD_ULVL_DENIED:
* Command's user level is higher than current user level, so access
* is denied.
* CMD_NOT_FOUND:
* Since these same return values are used for each command function
* plus the docommand() function, this error indicates that docommand()
* could not even find the command in the command table.
* CMD_MONRC_DENIED:
* The command cannot execute because it is considered illegal
* when run from within the monrc file.
*/
#define CMD_SUCCESS 0
#define CMD_FAILURE -1
#define CMD_PARAM_ERROR -2
#define CMD_LINE_ERROR -3
#define CMD_ULVL_DENIED -4
#define CMD_NOT_FOUND -5
#define CMD_MONRC_DENIED -6
/* Notes on help text array:
* The monitor's CLI processor assumes that every command's help text
* array abides by a few basic rules...
* First of all, it assumes that every array has AT LEAST two strings.
* The first string in the array of strings is assumed to be a one-line
* abstract describing the command.
* The second string in the array of strings is assumed to be a usage
* message that describes the syntax of the arguments needed by the command.
* If this second string is an empty string (""), the docommand() prints out
* a generic usage string indicating that there are no options or arguements
* to apply to the command.
* All remaining lines are formatted based on the needs of the individual
* command and the final string is a null pointer to let the CLI processor
* know where the end is.
* Following is an example help text array...
*
* char *HelpHelp[] = {
* "Display command set",
* "-[d] [commandname]",
* "Options:",
* " -d list commands and descriptions",
* 0,
* };
*
*/
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,262 @@
/* monlib.h:
* This header file is used by both the monitor and the application that
* may reside on top of the monitor.
* General notice:
* This code is part of a boot-monitor package developed as a generic base
* platform for embedded system designs. As such, it is likely to be
* distributed to various projects beyond the control of the original
* author. Please notify the author of any enhancements made or bugs found
* so that all may benefit from the changes. In addition, notification back
* to the author will allow the new user to pick up changes that may have
* been made by other users after this version of the code was distributed.
*
* Note1: the majority of this code was edited with 4-space tabs.
* Note2: as more and more contributions are accepted, the term "author"
* is becoming a mis-representation of credit.
*
* Original author: Ed Sutter
* Email: esutter@lucent.com
* Phone: 908-582-2351
*/
#ifndef _MONLIB_H_
#define _MONLIB_H_
#include <umon/tfs.h>
#include <umon/cli.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* The following additions are RTEMS specific.
*/
#if defined(__rtems__)
/*
* RTEMS uMonitor wrapper for monConnect(). This will deal with the
* getting MONCOMPTR as well as providing the locking routines.
*/
void rtems_umon_connect(void);
/*
* BSP specific routine to help when calling monConnect(). This
* returns the value known to uMon as MONCOMPTR.
*/
void *rtems_bsp_get_umon_monptr(void);
/*
* Initialize the TFS-RTEMS file system
*/
int rtems_initialize_tfs_filesystem(
const char *path
);
#endif
extern int monConnect(int (*monptr)(int,void *,void *,void *),
void (*lock)(void),void (*unlock)(void));
extern void mon_getargv(int *argc,char ***argv);
extern void mon_intsrestore(unsigned long oldval);
extern void mon_appexit(int exit_value);
extern void mon_free(char *buffer);
extern void mon_profiler(void *pdata);
extern void mon_bbc(char *filename, int linenum);
extern void mon_warmstart(unsigned long mask);
extern void mon_delay(long msec);
extern void mon_printpkt(char *buf, int size, int incoming);
extern void mon_printmem(char *mem, int size, int ascii);
extern int mon_com(int cmd,void *arg1,void *arg2,void *arg3);
extern int mon_timer(int cmd, void * arg);
extern int mon_setenv(char *varname,char *value);
extern int mon_putchar(char c);
extern int mon_getchar(void);
extern int mon_gotachar(void);
extern int mon_getbytes(char *buf,int count,int block);
extern int mon_restart(int restart_value);
extern int mon_tfsinit(void);
extern int mon_tfsunlink(char *filename);
extern int mon_tfslink(char *source, char *target);
extern int mon_tfsrun(char **arglist,int verbosity);
extern int mon_tfsfstat(char *filename,struct tfshdr *tfp);
extern int mon_tfseof(int file_descriptor);
extern int mon_tfstruncate(int file_descriptor,long length);
extern int mon_tfsread(int file_descriptor,char *buffer,int size);
extern int mon_tfswrite(int file_descriptor,char *buffer,int size);
extern int mon_tfsopen(char *filename,long mode,char *buffer);
extern int mon_tfsclose(int file_descriptor,char *info);
extern int mon_tfsseek(int file_descriptor,int offset,int whence);
extern int mon_tfsgetline(int file_descriptor,char *buffer,int bufsize);
extern int mon_tfsipmod(char *name,char *buffer,int offset,int size);
extern int mon_addcommand(struct monCommand *command_list,char *);
extern int mon_docommand(char *cmdline,int verbosity);
extern int mon_getline(char *buffer,int max,int ledit);
extern int mon_decompress(char *src,int srcsize,char *dest);
extern int mon_heapextend(char *base,int size);
extern int mon_pcicfgwrite(int interface,int bus,int dev,int func,int reg,
unsigned long val);
extern int mon_tfsadd(char *filename, char *info, char *flags,
unsigned char *src, int size);
extern int mon_i2cwrite(int interface, int bigaddr, unsigned char *data,
int len);
extern int mon_i2cread(int interface, int bigaddr, unsigned char *data,
int len);
extern int mon_sendenetpkt(char *pkt, int len);
extern int mon_recvenetpkt(char *pkt, int len);
extern int mon_flashoverride(void *flashinfo, int get, int bank);
extern int mon_flasherase(int snum);
extern int mon_flashwrite(char *dest,char *src, int bytecnt);
extern int mon_flashinfo(int snum,int *size, char **base);
extern int mon_watchdog(void);
extern int mon_timeofday(int cmd, void *arg);
extern char *mon_getsym(char *symname, char *buf, int bufsize);
extern char *mon_getenv(char *varname);
extern char *mon_getenvp(void);
extern char *mon_version(void);
#ifdef MALLOC_DEBUG
extern char *mon_malloc(int size,char *file, int line);
extern char *mon_realloc(char *buf,int size,char *file, int line);
#else
extern char *mon_malloc(int size);
extern char *mon_realloc(char *buf,int size);
#endif
extern long mon_tfsctrl(int command,long arg1,long arg2);
extern long mon_tfstell(int file_descriptor);
extern long mon_portcmd(int cmd, void *arg);
extern unsigned short mon_xcrc16(char *buffer,long length);
extern unsigned long mon_intsoff(void);
extern unsigned long mon_pcicfgread(int interface,int bus,int dev,
int func,int reg);
extern unsigned long mon_pcictrl(int interface, int cmd,
unsigned long arg1, unsigned long arg2);
extern unsigned long mon_i2cctrl(int interface, int cmd,
unsigned long arg1, unsigned long arg2);
extern unsigned long mon_assignhandler(long hnum,
unsigned long arg1,unsigned long arg2);
extern struct tfshdr *mon_tfsnext(struct tfshdr *tfp);
extern struct tfshdr *mon_tfsstat(char *filename);
#if SHOWVARARGS
extern void mon_memtrace(char *fmt, ...);
extern int mon_printf(char *fmt, ...);
extern int mon_cprintf(char *fmt, ...);
extern int mon_sprintf(char *,char *fmt, ...);
#else
extern void mon_memtrace();
extern int mon_printf();
extern int mon_cprintf();
extern int mon_sprintf();
#endif
#ifdef __cplusplus
}
#endif
/* defines used by monConnect():
*/
#define GETMONFUNC_PUTCHAR 1
#define GETMONFUNC_GETCHAR 2
#define GETMONFUNC_GOTACHAR 3
#define GETMONFUNC_GETBYTES 4
#define GETMONFUNC_PRINTF 5
#define GETMONFUNC_CPRINTF 6
#define GETMONFUNC_SPRINTF 7
#define GETMONFUNC_RESTART 8
#define GETMONFUNC_GETENV 9
#define GETMONFUNC_SETENV 10
#define GETMONFUNC_TFSINIT 11
#define GETMONFUNC_TFSADD 12
#define GETMONFUNC_TFSUNLINK 13
#define GETMONFUNC_TFSRUN 14
#define GETMONFUNC_TFSNEXT 15
#define GETMONFUNC_TFSSTAT 16
#define GETMONFUNC_TFSREAD 17
#define GETMONFUNC_TFSWRITE 18
#define GETMONFUNC_TFSOPEN 19
#define GETMONFUNC_TFSCLOSE 20
#define GETMONFUNC_TFSSEEK 21
#define GETMONFUNC_TFSGETLINE 22
#define GETMONFUNC_TFSIPMOD 23
#define GETMONFUNC_TFSCTRL 24
#define GETMONFUNC_ADDCOMMAND 25
#define GETMONFUNC_DOCOMMAND 26
#define GETMONFUNC_GETARGV 27
#define GETMONFUNC_CRC16 28
#define GETMONFUNC_CRC32 29
#define GETMONFUNC_PIOGET 30 /* NA (removed as of 1.0) */
#define GETMONFUNC_PIOSET 31 /* NA (removed as of 1.0) */
#define GETMONFUNC_PIOCLR 32 /* NA (removed as of 1.0) */
#define GETMONFUNC_INTSOFF 33
#define GETMONFUNC_INTSRESTORE 34
#define GETMONFUNC_APPEXIT 35
#define GETMONFUNC_MALLOC 36
#define GETMONFUNC_FREE 37
#define GETMONFUNC_GETLINE 38
#define GETMONFUNC_TFSFSTAT 39
#define GETMONFUNC_TFSEOF 40
#define GETMONFUNC_DECOMPRESS 41
#define GETMONFUNC_TFSTRUNCATE 42
#define GETMONFUNC_HEAPXTEND 43
#define GETMONFUNC_PROFILER 44
#define GETMONFUNC_TFSLINK 45
#define GETMONFUNC_BBC 46
#define GETMONFUNC_MEMTRACE 47
#define GETMONFUNC_TFSTELL 48
#define GETMONFUNC_VERSION 49
#define GETMONFUNC_WARMSTART 50
#define GETMONFUNC_PCICFGREAD 51
#define GETMONFUNC_PCICFGWRITE 52
#define GETMONFUNC_PCICONTROL 53
#define GETMONFUNC_I2CREAD 54
#define GETMONFUNC_I2CWRITE 55
#define GETMONFUNC_I2CCONTROL 56
#define GETMONFUNC_MONDELAY 57
#define GETMONFUNC_GETENVP 58
#define GETMONFUNC_REALLOC 59
#define GETMONFUNC_SENDENETPKT 60
#define GETMONFUNC_RECVENETPKT 61
#define GETMONFUNC_GETSYM 62
#define GETMONFUNC_PRINTPKT 63
#define GETMONFUNC_FLASHWRITE 64
#define GETMONFUNC_FLASHERASE 65
#define GETMONFUNC_FLASHINFO 66
#define GETMONFUNC_ASSIGNHDLR 67
#define GETMONFUNC_WATCHDOG 68
#define GETMONFUNC_PRINTMEM 69
#define GETMONFUNC_PORTCMD 70
#define GETMONFUNC_TIMEOFDAY 71
#define GETMONFUNC_TIMER 72
#define GETMONFUNC_FLASHOVRRD 73
#define CACHEFTYPE_DFLUSH 200
#define CACHEFTYPE_IINVALIDATE 201
#define CHARFUNC_PUTCHAR 300
#define CHARFUNC_GETCHAR 301
#define CHARFUNC_GOTACHAR 302
#define CHARFUNC_RAWMODEON 303
#define CHARFUNC_RAWMODEOFF 304
#define ASSIGNFUNC_GETUSERLEVEL 400
/* Defines used by mon_warmstart():
*/
#define WARMSTART_IOINIT 0x00000001
#define WARMSTART_BSSINIT 0x00000002
#define WARMSTART_RUNMONRC 0x00000004
#define WARMSTART_MONHEADER 0x00000008
#define WARMSTART_TFSAUTOBOOT 0x00000010
#define WARMSTART_BOARDINFO 0x00000020
#define WARMSTART_ALL 0xffffffff
#endif

View File

@@ -0,0 +1,187 @@
/* tfs.h:
* Header file for TFS transactions, used by both application and monitor.
*
* General notice:
* This code is part of a boot-monitor package developed as a generic base
* platform for embedded system designs. As such, it is likely to be
* distributed to various projects beyond the control of the original
* author. Please notify the author of any enhancements made or bugs found
* so that all may benefit from the changes. In addition, notification back
* to the author will allow the new user to pick up changes that may have
* been made by other users after this version of the code was distributed.
*
* Note1: the majority of this code was edited with 4-space tabs.
* Note2: as more and more contributions are accepted, the term "author"
* is becoming a mis-representation of credit.
*
* Original author: Ed Sutter
* Email: esutter@lucent.com
* Phone: 908-582-2351
*/
#ifndef _tfs_h
#define _tfs_h
#define TFSINFOSIZE 23 /* Max size of info string (mod4-1). */
#ifndef TFSNAMESIZE /* This specifies the maximum size of a file */
#define TFSNAMESIZE 23 /* name that can be used in TFS. */
#endif /* This MUST be some value mod4 - 1. */
#ifndef TFS_CHANGELOG_FILE /* Information used for change-log */
#define TFS_CHANGELOG_SIZE 0 /* facility within tfs. */
#define TFS_CHANGELOG_FILE ".tfschlog"
#endif
#ifndef SYMFILE /* This specifies the default filename */
#define SYMFILE "symtbl" /* used by the monitor for the symbol */
#endif /* table. */
#define MINUSRLEVEL 0 /* Minimum user level supported. */
#define MAXUSRLEVEL 3 /* Maximum user level supported. */
#ifndef TFS_RESERVED
#define TFS_RESERVED 4 /* Number of "reserved" entries (ulong) */
#endif /* in the TFS header. */
/* Flags: */
#define TFS_EXEC 0x00000001 /* 'e': Executable script. */
#define TFS_BRUN 0x00000002 /* 'b': To be executed at boot. */
#define TFS_QRYBRUN 0x00000004 /* 'B': To be executed at boot if */
/* query passes. */
#define TFS_SYMLINK 0x00000008 /* 'l': Symbolic link file. */
#define TFS_EBIN 0x00000010 /* 'E': Executable binary (coff/elf/a.out). */
#define TFS_CPRS 0x00000040 /* 'c': File is compressed. */
#define TFS_IPMOD 0x00000080 /* 'i': File is in-place modifiable. */
#define TFS_UNREAD 0x00000100 /* 'u': File is not even readable if the */
/* user-level requirement is not met; */
/* else, it is read-only. */
#define TFS_ULVLMSK 0x00000600 /* User level mask defines 4 access levels: */
#define TFS_ULVL0 0x00000000 /* '0' level 0 */
#define TFS_ULVL1 0x00000200 /* '1' level 1 */
#define TFS_ULVL2 0x00000400 /* '2' level 2 */
#define TFS_ULVL3 0x00000600 /* '3' level 3 */
#define TFS_NSTALE 0x00000800 /* File is NOT stale, invisible to user.
* When this bit is clear, the file is
* considered stale (see notes in tfsadd()).
* See notes in tfsclose() for this.
*/
#define TFS_ACTIVE 0x00008000 /* Used to indicate that file is not deleted. */
#define TFS_ULVLMAX TFS_ULVL3
#define TFS_USRLVL(f) ((f->flags & TFS_ULVLMSK) >> 9)
/* Open modes */
#define TFS_RDONLY 0x00010000 /* File is opened for reading. */
#define TFS_CREATE 0x00020000 /* File is to be created. Error if file */
/* with the same name already exists. */
#define TFS_APPEND 0x00040000 /* Append to existing file. If OR'ed */
/* with TFS_CREATE, then create if */
/* necessary. */
#define TFS_ALLFFS 0x00080000 /* File is created with all FFs. */
#define TFS_CREATERM 0x00100000 /* File is to be created. If file with */
/* same name already exists, then allow */
/* tfsadd() to remove it if necessary. */
/* The function tfsrunrc() will search through the current file set and */
/* if the file defined by TFS_RCFILE exists, it will be executed. */
/* If this file exists, it will NOT be run by tfsrunboot(). */
#define TFS_RCFILE "monrc"
/* Requests that can be made to tfsctrl(): */
#define TFS_ERRMSG 1
#define TFS_MEMUSE 2
#define TFS_MEMDEAD 3
#define TFS_DEFRAG 4
#define TFS_TELL 5
#define TFS_UNOPEN 7
#define TFS_FATOB 8
#define TFS_FBTOA 9
#define TFS_MEMAVAIL 10
#define TFS_TIMEFUNCS 11
#define TFS_DOCOMMAND 12
#define TFS_INITDEV 13
#define TFS_CHECKDEV 14
#define TFS_DEFRAGDEV 15
#define TFS_DEFRAGOFF 16
#define TFS_DEFRAGON 17
#define TFS_HEADROOM 18
#define TFS_FCOUNT 19
/* struct tfshdr:
* It is in FLASH as part of the file system to record the attributes of
* the file at the time of creation.
*/
struct tfshdr {
unsigned short hdrsize; /* Size of this header. */
unsigned short hdrvrsn; /* Header version #. */
long filsize; /* Size of the file. */
long flags; /* Flags describing the file. */
unsigned long filcrc; /* 32 bit CRC of file. */
unsigned long hdrcrc; /* 32 bit CRC of the header. */
unsigned long modtime; /* Time when file was last modified. */
struct tfshdr *next; /* Pointer to next file in list. */
char name[TFSNAMESIZE+1]; /* Name of file. */
char info[TFSINFOSIZE+1]; /* Miscellaneous info field. */
#if TFS_RESERVED
unsigned long rsvd[TFS_RESERVED];
#endif
};
#define TFSHDRSIZ sizeof(struct tfshdr)
/* TFS error returns. */
#define TFS_OKAY 0
#define TFSERR_NOFILE -1
#define TFSERR_NOSLOT -2
#define TFSERR_EOF -3
#define TFSERR_BADARG -4
#define TFSERR_NOTEXEC -5
#define TFSERR_BADCRC -6
#define TFSERR_FILEEXISTS -7
#define TFSERR_FLASHFAILURE -8
#define TFSERR_WRITEMAX -9
#define TFSERR_RDONLY -10
#define TFSERR_BADFD -11
#define TFSERR_BADHDR -12
#define TFSERR_CORRUPT -13
#define TFSERR_MEMFAIL -14
#define TFSERR_NOTIPMOD -16
#define TFSERR_MUTEXFAILURE -17
#define TFSERR_FLASHFULL -18
#define TFSERR_USERDENIED -19
#define TFSERR_NAMETOOBIG -20
#define TFSERR_FILEINUSE -21
#define TFSERR_NOTCPRS -22
#define TFSERR_NOTAVAILABLE -23
#define TFSERR_BADFLAG -24
#define TFSERR_CLEANOFF -25
#define TFSERR_FLAKEYSOURCE -26
#define TFSERR_BADEXTENSION -27
#define TFSERR_MIN -100
/* TFS seek options. */
#define TFS_BEGIN 1
#define TFS_CURRENT 2
#define TFS_END 3
/* Macros: */
#define TFS_DELETED(fp) (!((fp)->flags & TFS_ACTIVE))
#define TFS_FILEEXISTS(fp) ((fp)->flags & TFS_ACTIVE)
#define TFS_ISCPRS(fp) ((fp)->flags & TFS_CPRS)
#define TFS_ISEXEC(fp) ((fp)->flags & TFS_EXEC)
#define TFS_ISBOOT(fp) ((fp)->flags & TFS_BRUN)
#define TFS_ISLINK(fp) ((fp)->flags & TFS_SYMLINK)
#define TFS_STALE(fp) (!((fp)->flags & TFS_NSTALE))
#define TFS_FLAGS(fp) ((fp)->flags)
#define TFS_NAME(fp) ((fp)->name)
#define TFS_SIZE(fp) ((fp)->filsize)
#define TFS_TIME(fp) ((fp)->modtime)
#define TFS_INFO(fp) ((fp)->info)
#define TFS_NEXT(fp) ((fp)->next)
#define TFS_CRC(fp) ((fp)->filcrc)
#define TFS_ENTRY(fp) ((fp)->entry)
#define TFS_BASE(fp) ((char *)(fp)+(fp)->hdrsize)
typedef struct tfshdr TFILE;
#endif

View File

@@ -0,0 +1,726 @@
/*
* MicroMonitor TFS Hookup to RTEMS FS
*
* Initial release: Oct 1, 2004 by Ed Sutter
*
* This code was derived from the tftpDriver.c code written by
* W. Eric Norum, which was apparently derived from the IMFS driver.
*
* This code was updated and merged with RTEMS CVS by Joel Sherrill, 2009.
*
* $Id$
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/libio_.h>
#include <rtems/seterr.h>
#include <rtems/bspIo.h>
#include <umon/tfs.h>
#include <umon/monlib.h>
#ifdef RTEMS_TFS_DRIVER_DEBUG
#define RTEMS_TFS_DEBUG 1
#else
#define RTEMS_TFS_DEBUG 0
#endif
#define MAXFILESIZE 0x4000
#define MAXTFDS 15
/* Define these for thread safety...
*/
#ifndef newlib_tfdlock
#define newlib_tfdlock()
#endif
#ifndef newlib_tfdunlock
#define newlib_tfdunlock()
#endif
/* TFS file descriptor info:
*/
struct tfdinfo {
int inuse;
int tfd;
char *buf;
char name[TFSNAMESIZE+1];
char info[TFSNAMESIZE+1];
} tfdtable[MAXTFDS];
/*
* Pathname prefix
*/
char TFS_PATHNAME_PREFIX[128];
/*
* Root node_access value
* By using the address of a local static variable
* we ensure a unique value for this identifier.
*/
#define ROOT_NODE_ACCESS (&tfs_mutex)
/* Number of streams open at the same time
*/
static rtems_id tfs_mutex;
extern rtems_filesystem_operations_table rtems_tfs_ops;
extern rtems_filesystem_file_handlers_r rtems_tfs_handlers;
/* Direct copy from the IMFS. Look at this.
*/
rtems_filesystem_limits_and_options_t rtems_tfs_limits_and_options = {
5, /* link_max */
6, /* max_canon */
7, /* max_input */
255, /* name_max */
255, /* path_max */
2, /* pipe_buf */
1, /* posix_async_io */
2, /* posix_chown_restrictions */
3, /* posix_no_trunc */
4, /* posix_prio_io */
5, /* posix_sync_io */
6 /* posix_vdisable */
};
static int rtems_tfs_mount_me(
rtems_filesystem_mount_table_entry_t *temp_mt_entry
)
{
rtems_status_code sc;
temp_mt_entry->mt_fs_root.handlers = &rtems_tfs_handlers;
temp_mt_entry->mt_fs_root.ops = &rtems_tfs_ops;
/* We have no TFS specific data to maintain. This filesystem
* may only be mounted once. And we maintain no real filesystem
* nodes, so there is no real root.
*/
temp_mt_entry->fs_info = NULL;
temp_mt_entry->mt_fs_root.node_access = ROOT_NODE_ACCESS;
/* These need to be looked at for full POSIX semantics.
*/
temp_mt_entry->pathconf_limits_and_options = rtems_tfs_limits_and_options;
/* Now allocate a semaphore for mutual exclusion.
* NOTE: This could be in an fsinfo for this filesystem type.
*/
sc = rtems_semaphore_create (
rtems_build_name('U', 'M', 'O', 'N'),
1,
RTEMS_FIFO |
RTEMS_BINARY_SEMAPHORE |
RTEMS_NO_INHERIT_PRIORITY |
RTEMS_NO_PRIORITY_CEILING |
RTEMS_LOCAL,
0,
&tfs_mutex);
if (sc != RTEMS_SUCCESSFUL)
rtems_set_errno_and_return_minus_one( ENOMEM );
return 0;
}
/* Initialize the TFS-RTEMS file system
*/
int rtems_initialize_tfs_filesystem(
const char *path
)
{
int status;
rtems_filesystem_mount_table_entry_t *entry;
if (!path) {
printk( "TFS: No mount point specified\n" );
return -1;
}
strncpy( TFS_PATHNAME_PREFIX, path, sizeof(TFS_PATHNAME_PREFIX) );
status = mkdir( TFS_PATHNAME_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO );
if ( status == -1 ) {
printk( "TFS: Unable to mkdir %s\n", TFS_PATHNAME_PREFIX );
return status;
}
status = mount( &entry, &rtems_tfs_ops, RTEMS_FILESYSTEM_READ_WRITE,
NULL, TFS_PATHNAME_PREFIX);
if (status) {
printk( "TFS: Unable to mount on %s\n", TFS_PATHNAME_PREFIX );
perror("TFS mount failed");
}
return(status);
}
static int rtems_tfs_evaluate_for_make(
const char *path,
rtems_filesystem_location_info_t *pathloc,
const char **name
)
{
pathloc->node_access = NULL;
rtems_set_errno_and_return_minus_one( EIO );
}
/*
* Convert a path to canonical form
*/
static void fixPath(char *path)
{
char *inp, *outp, *base;
outp = inp = path;
base = NULL;
for (;;) {
if (inp[0] == '.') {
if (inp[1] == '\0')
break;
if (inp[1] == '/') {
inp += 2;
continue;
}
if (inp[1] == '.') {
if (inp[2] == '\0') {
if ((base != NULL) && (outp > base)) {
outp--;
while ((outp > base) && (outp[-1] != '/'))
outp--;
}
break;
}
if (inp[2] == '/') {
inp += 3;
if (base == NULL)
continue;
if (outp > base) {
outp--;
while ((outp > base) && (outp[-1] != '/'))
outp--;
}
continue;
}
}
}
if (base == NULL)
base = inp;
while (inp[0] != '/') {
if ((*outp++ = *inp++) == '\0')
return;
}
*outp++ = '/';
while (inp[0] == '/')
inp++;
}
*outp = '\0';
}
static int rtems_tfs_eval_path(
const char *pathname,
int flags,
rtems_filesystem_location_info_t *pathloc
)
{
pathloc->handlers = &rtems_tfs_handlers;
/*
* Hack to provide the illusion of directories inside the TFS file system.
* Paths ending in a / are assumed to be directories.
*/
if (pathname[strlen(pathname)-1] == '/') {
int isRelative = (pathloc->node_access != ROOT_NODE_ACCESS);
char *cp;
/*
* Reject attempts to open() directories
*/
if (flags & RTEMS_LIBIO_PERMS_RDWR)
rtems_set_errno_and_return_minus_one( EISDIR );
if (isRelative) {
cp = malloc (strlen(pathloc->node_access)+strlen(pathname)+1);
if (cp == NULL)
rtems_set_errno_and_return_minus_one( ENOMEM );
strcpy (cp, pathloc->node_access);
strcat (cp, pathname);
} else {
cp = strdup (pathname);
if (cp == NULL)
rtems_set_errno_and_return_minus_one( ENOMEM );
}
fixPath (cp);
pathloc->node_access = cp;
return 0;
}
if (pathloc->node_access != ROOT_NODE_ACCESS)
pathloc->node_access = 0;
/*
* Reject it if it's not read-only or write-only.
*/
flags &= RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE;
if ((flags != RTEMS_LIBIO_PERMS_READ) && (flags != RTEMS_LIBIO_PERMS_WRITE) )
rtems_set_errno_and_return_minus_one( EINVAL );
return 0;
}
/*
* The routine which does most of the work for the IMFS open handler
* The full_path_name here is all text AFTER the TFS_PATHNAME_PREFIX
* string, so if the filename is "/TFS/abc", the full_path_name string
* is "abc"...
*
* Attempts to remap the incoming flags to TFS equivalent.
* Its not a perfect mapping, but gets pretty close.
* A comma-delimited path is supported to allow the user
* to specify TFS-stuff (flag string, info string, and a buffer).
* For example:
* abc,e,script,0x400000
* This is a file called "abc" that will have the TFS 'e' flag
* and the TFS info field of "script". The storage buffer is
* supplied by the user at 0x400000.
*/
static int rtems_tfs_open_worker(
rtems_libio_t *iop,
char *path,
uint32_t flags,
uint32_t mode
)
{
static int beenhere = 0;
long flagmode;
int tfdidx, tfd;
struct tfdinfo *tip;
char *buf, *fstr, *istr, *bstr, pathcopy[TFSNAMESIZE*3+1];
if (RTEMS_TFS_DEBUG)
printk("_open_r(%s,0x%" PRIx32 ",0x%" PRIx32 ")\n",path,flags,mode);
if (!beenhere) {
newlib_tfdlock();
for(tfdidx=0;tfdidx<MAXTFDS;tfdidx++)
tfdtable[tfdidx].inuse = 0;
tfdtable[0].inuse = 1; /* fake entry for stdin */
tfdtable[1].inuse = 1; /* fake entry for stdout */
tfdtable[2].inuse = 1; /* fake entry for stderr */
newlib_tfdunlock();
beenhere = 1;
}
istr = fstr = bstr = buf = (char *)0;
/* Copy the incoming path to a local array so that we can safely
* modify the string...
*/
if (strlen(path) > TFSNAMESIZE*3) {
return(ENAMETOOLONG);
}
strcpy(pathcopy,path);
/* The incoming string may have commas that are used to delimit the
* name from the TFS flag string, TFS info string and buffer.
* Check for the commas and test for maximum string length...
*/
fstr = strchr(pathcopy,',');
if (fstr) {
*fstr++ = 0;
istr = strchr(fstr,',');
if (istr) {
*istr++ = 0;
bstr = strchr(istr,',');
if (bstr)
*bstr++ = 0;
}
}
if (strlen(pathcopy) > TFSNAMESIZE) {
return(ENAMETOOLONG);
}
if (istr) {
if (strlen(istr) > TFSNAMESIZE) {
return(ENAMETOOLONG);
}
}
/* If O_EXCL and O_CREAT are set, then fail if the file exists...
*/
if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
if (mon_tfsstat((char *)pathcopy)) {
return(EEXIST);
}
}
/* Only a few flag combinations are supported...
* O_RDONLY Simple read-only
* O_WRONLY | O_APPEND Each write starts at end of file
* O_WRONLY | O_TRUNC If file exists, truncate it
* O_WRONLY | O_CREAT Create if it doesn't exist
* O_WRONLY | O_CREAT | O_EXCL Fail if file exists
*/
switch(flags & O_ACCMODE) {
case O_RDONLY:
flagmode = TFS_RDONLY;
break;
case O_WRONLY|O_APPEND:
flagmode = TFS_APPEND;
break;
case O_WRONLY|O_TRUNC:
case O_WRONLY|O_CREAT|O_TRUNC:
mon_tfsunlink((char *)pathcopy);
flagmode = TFS_CREATE|TFS_APPEND;
break;
case O_WRONLY|O_CREAT:
case O_WRONLY|O_CREAT|O_APPEND:
flagmode = TFS_CREATE|TFS_APPEND;
break;
case O_RDWR:
case O_WRONLY|O_CREAT|O_EXCL:
flagmode = TFS_CREATE|TFS_APPEND;
break;
default:
printk("_open_r(): flag 0x%" PRIx32 " not supported\n",flags);
return(ENOTSUP);
}
/* Find an open slot in our tfd table:
*/
newlib_tfdlock();
for(tfdidx=0;tfdidx<MAXTFDS;tfdidx++) {
if (tfdtable[tfdidx].inuse == 0)
break;
}
if (tfdidx == MAXTFDS) {
newlib_tfdunlock();
return(EMFILE);
}
tip = &tfdtable[tfdidx];
tip->inuse = 1;
newlib_tfdunlock();
/* If file is opened for something other than O_RDONLY, then
* we need to allocate a buffer for the file..
* WARNING: It is the user's responsibility to make sure that
* the file size does not exceed this buffer. Note that the
* buffer may be specified as part of the comma-delimited path.
*/
if (flagmode == TFS_RDONLY) {
buf = (char *)0;
} else {
if (bstr)
buf = (char *)strtol(bstr,0,0);
else
buf = malloc(MAXFILESIZE);
if (!buf) {
newlib_tfdlock();
tip->inuse = 0;
newlib_tfdunlock();
return(ENOMEM);
}
}
/* Deal with tfs flags and tfs info fields if necessary:
*/
if (fstr) {
long bflag;
bflag = mon_tfsctrl(TFS_FATOB,(long)fstr,0);
if (bflag == -1) {
return(EINVAL);
}
flagmode |= bflag;
}
if (istr)
strcpy(tip->info,istr);
else
tip->info[0] = 0;
tfd = mon_tfsopen((char *)pathcopy,flagmode,buf);
if (tfd >= 0) {
tip->tfd = tfd;
tip->buf = buf;
strcpy(tip->name,pathcopy);
iop->file_info = (void *)tfdidx;
return(0);
} else {
printk("%s: %s\n",pathcopy,
(char *)mon_tfsctrl(TFS_ERRMSG,tfd,0));
}
if (buf)
free(buf);
newlib_tfdlock();
tip->inuse = 0;
newlib_tfdunlock();
return(EINVAL);
}
/*
* The IMFS open handler
*/
static int rtems_tfs_open(
rtems_libio_t *iop,
const char *new_name,
uint32_t flags,
uint32_t mode
)
{
char *full_path_name;
char *s1;
int err;
if (RTEMS_TFS_DEBUG)
printk("rtems_tfs_open(%s)\n",new_name);
/*
* Tack the `current directory' on to relative paths.
* We know that the current directory ends in a / character.
*/
if (*new_name == '/') {
/*
* Skip the TFS filesystem prefix.
*/
int len = strlen (TFS_PATHNAME_PREFIX);
if (strncmp (new_name, TFS_PATHNAME_PREFIX, len))
return ENOENT;
new_name += len;
s1 = "";
} else {
s1 = rtems_filesystem_current.node_access;
}
full_path_name = malloc (strlen (s1) + strlen (new_name) + 1);
if (full_path_name == NULL)
return ENOMEM;
strcpy (full_path_name, s1);
strcat (full_path_name, new_name);
fixPath (full_path_name);
err = rtems_tfs_open_worker (iop, full_path_name, flags, mode);
free (full_path_name);
return err;
}
/*
* Read from an open TFS file...
*/
static ssize_t rtems_tfs_read(
rtems_libio_t *iop,
void *buffer,
uint32_t count
)
{
int ret, fd;
fd = (int) iop->file_info;
if (RTEMS_TFS_DEBUG)
printk("_read_r(%d,%" PRId32 ")\n",fd,count);
if ((fd < 3) || (fd >= MAXTFDS))
return(EBADF);
ret = mon_tfsread(tfdtable[fd].tfd,buffer,count);
if (ret == TFSERR_EOF)
ret = 0;
return(ret);
}
/*
* Close the open tfs file.
*/
static int rtems_tfs_close(
rtems_libio_t *iop
)
{
int fd;
char *info;
struct tfdinfo *tip;
fd = (int)iop->file_info;
if (RTEMS_TFS_DEBUG)
printk("rtems_tfs_close(%d)\n",fd);
if ((fd < 3) || (fd >= MAXTFDS)) {
rtems_set_errno_and_return_minus_one (EBADF);
}
tip = &tfdtable[fd];
if (tip->info[0])
info = tip->info;
else
info = (char *)0;
mon_tfsclose(tip->tfd,info);
if (tip->buf)
free(tip->buf);
newlib_tfdlock();
tip->inuse = 0;
newlib_tfdunlock();
return RTEMS_SUCCESSFUL;
}
static ssize_t rtems_tfs_write(
rtems_libio_t *iop,
const void *buffer,
uint32_t count
)
{
int ret, fd;
fd = (int) iop->file_info;
if (RTEMS_TFS_DEBUG)
printk("rtems_tfs_write(%d,%" PRId32" )\n",fd,count);
if ((fd <= 0) || (fd >= MAXTFDS)) {
rtems_set_errno_and_return_minus_one (EBADF);
}
ret = mon_tfswrite(tfdtable[fd].tfd,(char *)buffer,count);
if (ret < 0)
return(-1);
return(ret);
}
static rtems_off64_t rtems_tfs_lseek(
rtems_libio_t *iop,
rtems_off64_t offset,
int whence
)
{
int ret, fd;
fd = (int) iop->file_info;
if (RTEMS_TFS_DEBUG)
printk("rtems_tfs_lseek(%d,%ld,%d)\n",fd,(long)offset,whence);
switch (whence) {
case SEEK_END:
printk("rtems_tfs_lseek doesn't support SEEK_END\n");
return(-1);
case SEEK_CUR:
whence = TFS_CURRENT;
break;
case SEEK_SET:
whence = TFS_BEGIN;
break;
}
ret = mon_tfsseek(tfdtable[fd].tfd,offset,whence);
if (ret < 0)
return(-1);
return (rtems_off64_t)ret;
}
/*
*
*/
static int rtems_tfs_ftruncate(
rtems_libio_t *iop,
rtems_off64_t count
)
{
int ret, fd;
fd = (int) iop->file_info;
ret = mon_tfstruncate(tfdtable[fd].tfd,count);
if (ret != TFS_OKAY)
return(-1);
return(0);
}
static int rtems_tfs_ioctl(
rtems_libio_t *iop,
uint32_t cmd,
void *buf
)
{
int fd, ret;
fd = (int) iop->file_info;
ret = mon_tfsctrl(cmd,(long)buf,0);
return(-1);
}
static rtems_filesystem_node_types_t rtems_tfs_node_type(
rtems_filesystem_location_info_t *pathloc
)
{
if ((pathloc->node_access == NULL) ||
(pathloc->node_access == ROOT_NODE_ACCESS))
return RTEMS_FILESYSTEM_MEMORY_FILE;
return RTEMS_FILESYSTEM_DIRECTORY;
}
static int rtems_tfs_free_node_info(
rtems_filesystem_location_info_t *pathloc)
{
if (pathloc->node_access && (pathloc->node_access != ROOT_NODE_ACCESS)) {
free (pathloc->node_access);
pathloc->node_access = NULL;
}
return 0;
}
rtems_filesystem_operations_table rtems_tfs_ops = {
rtems_tfs_eval_path, /* eval_path */
rtems_tfs_evaluate_for_make, /* evaluate_for_make */
NULL, /* link */
NULL, /* unlink */
rtems_tfs_node_type, /* node_type */
NULL, /* mknod */
NULL, /* chown */
rtems_tfs_free_node_info, /* freenodinfo */
NULL, /* mount */
rtems_tfs_mount_me, /* initialize */
NULL, /* unmount */
NULL, /* fsunmount */
NULL, /* utime */
NULL, /* evaluate_link */
NULL, /* symlink */
NULL, /* readlin */
};
rtems_filesystem_file_handlers_r rtems_tfs_handlers = {
rtems_tfs_open, /* open */
rtems_tfs_close, /* close */
rtems_tfs_read, /* read */
rtems_tfs_write, /* write */
rtems_tfs_ioctl, /* ioctl */
rtems_tfs_lseek, /* lseek */
NULL, /* fstat */
NULL, /* fchmod */
rtems_tfs_ftruncate, /* ftruncate */
NULL, /* fpathconf */
NULL, /* fsync */
NULL, /* fdatasync */
NULL, /* fcntl */
NULL /* rmnod */
};

View File

@@ -0,0 +1,26 @@
/*
* COPYRIGHT (c) 1989-2009.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#include <umon/monlib.h>
/* XXX eventually add lock/unlock methods */
void rtems_umon_connect(void)
{
void *moncomptr;
moncomptr = rtems_bsp_get_umon_monptr();
monConnect(
(int(*)())(*(unsigned long *)moncomptr), /* monitor base */
(void *)0, /* lock */
(void *)0 /* unlock */
);
}