FreeCalypso > hg > freecalypso-sw
changeset 221:842c9fd828fd
gsm-fw: TMFFS integrated
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Tue, 07 Jan 2014 03:51:09 +0000 |
parents | aa4ba71a1032 |
children | 02e80fcc3a5a |
files | gsm-fw/cfgmagic/feature.tmffs1 gsm-fw/cfgmagic/feature.tmffs2 gsm-fw/services/ffs/Makefile gsm-fw/services/ffs/core.c gsm-fw/services/ffs/task.c gsm-fw/services/ffs/tmffs.c |
diffstat | 6 files changed, 940 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/cfgmagic/feature.tmffs1 Tue Jan 07 03:51:09 2014 +0000 @@ -0,0 +1,8 @@ +if [ "$RVM_ETM_SWE" != 1 ] +then + echo "Error: feature tmffs1: need feature etm first" 1>&2 + exit 1 +fi + +TMFFS1=1 +export_to_c TMFFS1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/cfgmagic/feature.tmffs2 Tue Jan 07 03:51:09 2014 +0000 @@ -0,0 +1,8 @@ +if [ "$RVM_ETM_SWE" != 1 ] +then + echo "Error: feature tmffs2: need feature etm first" 1>&2 + exit 1 +fi + +TMFFS2=1 +export_to_c TMFFS2
--- a/gsm-fw/services/ffs/Makefile Mon Jan 06 20:50:33 2014 +0000 +++ b/gsm-fw/services/ffs/Makefile Tue Jan 07 03:51:09 2014 +0000 @@ -3,7 +3,7 @@ LD= arm-elf-ld OBJS= cfgffs.o core.o drv.o ffs_env.o ffs_target.o ffstrace.o fsck.o rand.o \ - reclaim.o task.o + reclaim.o task.o tmffs.o HDRS= core.h drv.h ffs.h ffs_api.h ffs_env.h ffs_pool_size.h ffstrace.h \ intctl.h ramffs.h task.h tmffs.h
--- a/gsm-fw/services/ffs/core.c Mon Jan 06 20:50:33 2014 +0000 +++ b/gsm-fw/services/ffs/core.c Tue Jan 07 03:51:09 2014 +0000 @@ -1344,11 +1344,8 @@ return error; } -/* FreeCalypso: stubbed out until we integrate TMFFS */ -#if 0 extern int tmffs_bufsize(void); // used by ffs_query() extern unsigned char *tmffs_bufaddr(void); // used by ffs_query() -#endif #if (TARGET == 1) // request_id_last is only used in TARGET not to any use on the PC side @@ -1418,11 +1415,8 @@ break; } -/* FreeCalypso: stubbed out until we integrate TMFFS */ -#if 0 case Q_TM_BUFADDR: *(uint32*)p = (uint32) tmffs_bufaddr(); break; case Q_TM_BUFSIZE: *(uint32*)p = tmffs_bufsize(); break; -#endif case Q_DEV_BASE: *(uint32*)p = (uint32) dev.base; break; // FFS versions
--- a/gsm-fw/services/ffs/task.c Mon Jan 06 20:50:33 2014 +0000 +++ b/gsm-fw/services/ffs/task.c Tue Jan 07 03:51:09 2014 +0000 @@ -290,10 +290,8 @@ // otherwise mkdir("pcm") will fail. error = ffs_mkdir_nb("/pcm", 0); -#if 0 // Register FFS to ETM database error = etm_ffs_init(); -#endif while (1) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/services/ffs/tmffs.c Tue Jan 07 03:51:09 2014 +0000 @@ -0,0 +1,923 @@ +/****************************************************************************** + * Flash File System (ffs) + * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com + * + * ffs testmode interface + * + * $Id: tmffs.c 1.51 Thu, 18 Dec 2003 10:50:52 +0100 tsj $ + * + ******************************************************************************/ + +#include "../../include/config.h" +#include "../../riviera/rv/rv_defined_swe.h" + +#ifdef RVM_ETM_SWE +#include "../etm/etm.h" +#include "../etm/etm_api.h" +#endif + +#include "ffs.h" +#include "task.h" +#include "ffstrace.h" +#include "tmffs.h" + +#include <string.h> + +/****************************************************************************** + * Local globals for all protocols + ******************************************************************************/ + +#if TMFFS1 || TMFFS2 +static int32 bufsize, tmpsize; +static uint8 stringsize; +#endif + +effs_t ffs_initialize(void); +effs_t ffs_exit(void); + +#define tmffs_put8(x) *outp++ = x; +#define tmffs_put16(x) *outp++ = (x & 0xff); *outp++ = (x>>8); + +// Not in use +//#define tmffs_put32(x) tmffs_put16(x); tmffs_put16(x >> 16); + +#ifdef RVM_ETM_SWE + +int etm_ffs2(T_ETM_PKT *pkt, unsigned char *inp, int insize); + +/****************************************************************************** + * TM FFS registration to ETM database + *****************************************************************************/ +/* Callback function registered in ETM database */ +int etm_ffs1_pkt_receive(uint8 *data, int size) +{ + int mid; + T_ETM_PKT *pkt; + + ttw(ttr(TTrTmffs, "etm_ffs1_pkt_receive(*, %d)" NL, size)); + + /* Create TestMode return Packet */ + if ((pkt = (T_ETM_PKT *) target_malloc(sizeof(T_ETM_PKT))) == NULL) { + ttw(ttr(TTrTmffs, "etm_ffs1_pkt_receive(): Limit of memory bank reached" NL)); + return ETM_NOMEM; + } + + // Max packet size for TM3 is 128 bytes + size = tm_ffs(pkt->data, TM3_PACKET_SIZE, data, size); + + pkt->size = size; + pkt->status = ETM_OK; + pkt->mid = ETM_FFS1; + + etm_pkt_send(pkt); + target_free(pkt); + + return ETM_OK; +} + +/* Callback function registered in ETM database */ +int etm_ffs2_pkt_receive(uint8 *data, int size) +{ + int status; + T_ETM_PKT *pkt = NULL; + + ttw(ttr(TTrTmffs, "etm_ffs2_pkt_receive(*, %d)" NL, size)); + + /* Create TestMode return Packet */ + if ((pkt = (T_ETM_PKT *) target_malloc(sizeof(T_ETM_PKT))) == NULL) { + ttw(ttr(TTrTmffs, "etm_ffs2_pkt_receive(): Limit of memory bank reached" NL)); + return ETM_NOMEM; + } + + status = etm_ffs2(pkt, data, size); + return status; +} +#endif + +/* Init of FFS in the ETM database */ +int etm_ffs_init(void) +{ + int status; + +#ifdef RVM_ETM_SWE + status = etm_register("FFS1", ETM_FFS1, 0, 0, etm_ffs1_pkt_receive); + status = etm_register("FFS2", ETM_FFS2, 0, 0, etm_ffs2_pkt_receive); +#else + status = 0; +#endif + return status; +} + +/****************************************************************************** + * FFS1 Protocol + ******************************************************************************/ + +#ifndef TMFFS1 + +int tm_ffs(unsigned char *outp, int outsize, unsigned char *inp, int insize) +{ + return -1; // FIXME handle error better +} + +// Note these functions must be presented because ffs_query() use them but +// they are only valid if FFS1_PROTOCOL is used. +int tmffs_bufsize(void) +{ + return EFFS_NOSYS; +} + +unsigned char *tmffs_bufaddr(void) +{ + return 0; +} + +#else + +#if (GSMLITE == 1) +#define TMFFS1_BUFFER_SIZE 4000 //previously 8192 +#else +#define TMFFS1_BUFFER_SIZE 8192 +#endif + +#define TMFFS1_STRING_SIZE 127 + +/****************************************************************************** + * Macros + ******************************************************************************/ + +#define tmffs1_putdata(outp, src, size) \ + tmffs_put8(FPI_DATA); \ + tmffs_put16(size); \ + memcpy(outp, src, size); \ + outp += size; + +/****************************************************************************** + * Local globals + ******************************************************************************/ + +static unsigned char buffer[TMFFS1_BUFFER_SIZE]; +static bufindex; + +static char string[TMFFS1_STRING_SIZE]; + +static effs_t tm_ffs_overflowck(void) +{ + if (bufsize > TMFFS1_BUFFER_SIZE || + stringsize > TMFFS1_STRING_SIZE) + return EFFS_TOOBIG; + + return EFFS_OK; +} + + +/****************************************************************************** + * tm_ffs + ******************************************************************************/ + +/** + * NOTEME: This has been introduced when the ffs 1MB device limit was + * broken. This made location_t go from uint16 to uint32, messing up + * with PCTM. + * + * This makes the xstat_s look the same to PCTM PC side, though + * location will be forced to 0. + */ +void hack_xstat_2_look_like_old_xstat(struct xstat_s *xstat) +{ + int i; + char *location; + + xstat->location = 0; + + for (location = (char *) &(xstat->location) + 2; location <= (char *) &(xstat->sequence); location++) + *location = location[2]; +} + +// Parse input message and execute function. Then fill output buffer with +// return values from the called function and transmit the message. Return +// number of bytes inserted into output buffer. If return value is negative, +// it represents an error code. +int tm_ffs(unsigned char *outp, int outsize, unsigned char *inp, int insize) +{ + int error; + tmffs_cid_t fid; + + unsigned char *outp_start = outp; + unsigned char *inp_start = inp; + + static uint8 i8[2]; static uint16 i8i; + static uint16 i16[2]; static uint16 i16i; + static uint32 i32[2]; static uint16 i32i; + + tw(tr(TR_BEGIN, TrTmffs, "TMFFS:\n")); + + while((fid = *inp++) != FPI_END) + { + switch(fid) + { + /********************************************************** + * Generic Protocol Functions + **********************************************************/ + + case FPI_BEGIN: + // for (i8i = 0; i8i < TMFFS1_STRING_SIZE; i8i++) // DEBUG + // string[i8i] = '#'; + // for (i8i = 0; i8i < TMFFS1_BUFFER_SIZE; i8i++) // DEBUG + // buffer[i8i] = '$'; + i8i = i16i = i32i = bufsize = stringsize = 0; + bufindex = 0; + i8[0] = i8[1] = 0; + i16[0] = i16[1] = 0; + i32[0] = i32[1] = 0; + string[0] = buffer[0] = 0; + tw(tr(TR_FUNC, TrTmffs, "FPI_BEGIN\n")); + ttw(ttr(TTrTmffs, "tm1" NL)); + break; + case FPI_TMFFS_VERSION: + // NULL -> UINT16 + tmffs_put16(TMFFS1_VERSION); + break; + + case FPI_INT8: + i8[i8i++] = inp[0]; inp += 1; + tw(tr(TR_FUNC, TrTmffs, "FPI_INT8(%d/0x%x)\n", + i8[i8i-1], i8[i8i-1])); + ttw(ttr(TTrTmffs, "tm_i8" NL)); + break; + case FPI_INT16: + i16[i16i++] = (inp[0]) | (inp[1] << 8); inp += 2; + tw(tr(TR_FUNC, TrTmffs, "FPI_INT16(%d/0x%x)\n", + i16[i16i-1], i16[i16i-1])); + ttw(ttr(TTrTmffs, "tm_i16" NL)); + break; + case FPI_INT32: + i32[i32i++] = inp[0] | (inp[1] << 8) + | (inp[2] << 16) | (inp[3] << 24); + inp += 4; + tw(tr(TR_FUNC, TrTmffs, "FPI_INT32(%d/0x%x)\n", + i32[i32i-1], i32[i32i-1])); + ttw(ttr(TTrTmffs, "tm_i32" NL)); + break; + case FPI_BUFFER: + bufsize = inp[0] | (inp[1] << 8); inp += 2; + tw(tr(TR_FUNC, TrTmffs, "FPI_BUFFER(%d)\n", bufsize)); + ttw(ttr(TTrTmffs, "tm_buf" NL)); + break; + case FPI_DATA: + bufsize = inp[0] | (inp[1] << 8); inp += 2; + memcpy(buffer, inp, bufsize); inp += bufsize; + tw(tr(TR_FUNC, TrTmffs, "FPI_DATA(%d)\n", bufsize)); + ttw(ttr(TTrTmffs, "tm_data" NL)); + break; + case FPI_STRBUF: + // string buffer size MUST include null-terminator! + stringsize = inp[0]; inp += 1; + tw(tr(TR_FUNC, TrTmffs, "FPI_STRBUF(%d)\n", stringsize)); + ttw(ttr(TTrTmffs, "tm_sbuf" NL)); + break; + case FPI_STRING: + // stringsize MUST include null-terminator! + // <INT8>, <BYTES> -> NULL (or ERROR) + stringsize = inp[0]; inp += 1; + if (stringsize <= TMFFS1_STRING_SIZE) + memcpy(string, inp, stringsize); + inp += stringsize; + tw(tr(TR_FUNC, TrTmffs, "FPI_STRING(%d,'%s')\n", + stringsize, string)); + ttw(ttr(TTrTmffs, "tm_s" NL)); + break; + + case FPI_BUFREAD: + // <INT16> -> DATA + tmpsize = inp[0] | (inp[1] << 8); inp += 2; + tw(tr(TR_FUNC, TrTmffs, "FPI_BUF_READ(%d)\n", tmpsize)); + tmffs1_putdata(outp, &buffer[bufindex], tmpsize); + bufindex += tmpsize; + ttw(ttr(TTrTmffs, "tm_bufrd" NL)); + break; + case FPI_BUFWRITE: + // <INT16>, <BYTES> -> NULL (or ERROR) + tmpsize = inp[0] | (inp[1] << 8); inp += 2; + tw(tr(TR_FUNC, TrTmffs, "FPI_BUF_WRITE(%d)\n", tmpsize)); + if (bufsize + tmpsize <= TMFFS1_BUFFER_SIZE) + memcpy(&buffer[bufsize], inp, tmpsize); + inp += tmpsize; + bufsize += tmpsize; + ttw(ttr(TTrTmffs, "tm_bufwr" NL)); + break; + case FPI_BUFSET: + bufindex = inp[0] | (inp[1] << 8); inp += 2; + tw(tr(TR_FUNC, TrTmffs, "FPI_BUF_SET(%d)\n", bufindex)); + ttw(ttr(TTrTmffs, "tm_bufset" NL)); + break; + + /********************************************************** + * FFS Functions + **********************************************************/ + + case FPI_PREFORMAT: + // NULL -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_preformat_nb(i16[0], 0); + if (error > 0) + error = 0; // ignore request id + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_PREFORMAT(0x%x)\n", i16[0])); + ttw(ttr(TTrTmffs, "tm_pfmt" NL)); + break; + case FPI_FORMAT: + // STRING -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_format_nb(&string[0], i16[0], 0); + if (error > 0) + error = 0; // ignore request id + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_FORMAT(0x%x)\n", i16[0])); + ttw(ttr(TTrTmffs, "tm_fmt" NL)); + break; + + + case FPI_FCREATE: + // STRING, DATA -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_fcreate_nb(string, buffer, bufsize, 0); + if (error > 0) + error = 0; // ignore request id + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_FCREATE('%s', 0x%x, %d/0x%x)\n", + string, buffer, bufsize, bufsize)); + ttw(ttr(TTrTmffs, "tm_fcr" NL)); + break; + case FPI_FUPDATE: + // STRING, DATA -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_fupdate_nb(string, buffer, bufsize, 0); + if (error > 0) + error = 0; // ignore request id + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_FUPDATE('%s', 0x%x, %d/0x%x)\n", + string, buffer, bufsize, bufsize)); + ttw(ttr(TTrTmffs, "tm_fup" NL)); + break; + case FPI_FWRITE: + // STRING, DATA -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_fwrite_nb(string, buffer, bufsize, 0); + if (error > 0) + error = 0; // ignore request id + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_FWRITE('%s', 0x%x, %d/0x%x)\n", + string, buffer, bufsize, bufsize)); + ttw(ttr(TTrTmffs, "tm_fwr" NL)); + break; + case FPI_FREAD: + // STRING, BUFFER -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_file_read(string, buffer, TMFFS1_BUFFER_SIZE); + // Because a 32-bit integer is returned, we have to saturate it + // into an 8-bit value. + if (error >= 0) + error = 0; + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_FREAD('%s', 0x%x, %d/0x%x)\n", + string, buffer, bufsize, bufsize)); + ttw(ttr(TTrTmffs, "tm_frd" NL)); + break; + case FPI_REMOVE: + // STRING -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_remove_nb(string, 0); + if (error > 0) + error = 0; // ignore request id + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_REMOVE()\n")); + ttw(ttr(TTrTmffs, "tm_rm" NL)); + break; + + + case FPI_MKDIR: + // STRING -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_mkdir_nb(string, 0); + if (error > 0) + error = 0; // ignore request id + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_MKDIR()\n")); + ttw(ttr(TTrTmffs, "tm_mkd" NL)); + break; + case FPI_OPENDIR: + // STRING, BUFFER -> ERROR, DATA + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_opendir(string, (struct dir_s *) buffer); + // Because a 32-bit integer is returned, we have to saturate it + // into an 8-bit value. + if (error >= 0) + error = 0; + tmffs_put8(error); + tmffs1_putdata(outp, buffer, sizeof(struct dir_s)); + tw(tr(TR_FUNC, TrTmffs, "FPI_OPENDIR()\n")); + ttw(ttr(TTrTmffs, "tm_od" NL)); + break; + case FPI_READDIR: + // DATA, STRBUF -> ERROR, DATA, STRING + string[0] = 0; + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_readdir((struct dir_s *) buffer, string, stringsize); + + // Saturate error(i) in order to let it fit in type int8. + if (error > 127) + error = 127; + tmffs_put8(error); + tmffs1_putdata(outp, buffer, sizeof(struct dir_s)); + stringsize = strlen(string) + 1; + tmffs_put8(FPI_STRING); // put directory entry's name... + tmffs_put8(stringsize); + memcpy(outp, string, stringsize); + outp += stringsize; + tw(tr(TR_FUNC, TrTmffs, "FPI_READDIR()\n")); + ttw(ttr(TTrTmffs, "tm_rdd" NL)); + break; + + + case FPI_STAT: + // STRING, BUFFER -> ERROR, DATA + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_stat(&string[0], (struct stat_s *) buffer); + tmffs_put8(error); + tmffs1_putdata(outp, buffer, sizeof(struct stat_s)); + tw(tr(TR_FUNC, TrTmffs, "FPI_STAT()\n")); + ttw(ttr(TTrTmffs, "tm_st" NL)); + break; + case FPI_LINKSTAT: + // STRING, BUFFER -> ERROR, DATA + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_xlstat(&string[0], (struct xstat_s *) buffer); + tmffs_put8(error); + + hack_xstat_2_look_like_old_xstat((struct xstat_s *) buffer); + + tmffs1_putdata(outp, buffer, sizeof(struct xstat_s) - 2); + tw(tr(TR_FUNC, TrTmffs, "FPI_()\n")); + ttw(ttr(TTrTmffs, "tm_lst" NL)); + break; + + + case FPI_SYMLINK: + // STRING, DATA -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_symlink_nb(string, (char *) buffer, 0); + if (error > 0) + error = 0; // ignore request id + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_SYMLINK()\n")); + ttw(ttr(TTrTmffs, "tm_sym" NL)); + break; + case FPI_READLINK: + // STRING, BUFFER -> ERROR, DATA + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_readlink(string, (char *) buffer, TMFFS1_BUFFER_SIZE); + // Because a 32-bit integer is returned, we have to saturate it + // into an 8-bit value. + if (error >= 0) + error = 0; + tmffs_put8(error); + tmffs1_putdata(outp, buffer, bufsize); // put link contents + tw(tr(TR_FUNC, TrTmffs, "FPI_READLINK()\n")); + ttw(ttr(TTrTmffs, "tm_rdl" NL)); + break; + + + case FPI_QUERY: + // INT8 -> ERROR, DATA + error = ffs_query(i8[0], buffer); + tmffs_put8(error); + tmffs1_putdata(outp, buffer, 16); + tw(tr(TR_FUNC, TrTmffs, "FPI_QUERY()\n")); + ttw(ttr(TTrTmffs, "tm_q" NL)); + break; + case FPI_FCONTROL: + // STRING INT8 INT32 -> ERROR + if ((error = tm_ffs_overflowck()) == EFFS_OK) + error = ffs_fcontrol_nb(string, i8[0], i32[0], 0); + if (error > 0) + error = 0; // ignore request id + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_FCONTROL()\n")); + ttw(ttr(TTrTmffs, "tm_fc" NL)); + break; + + case FPI_INIT: + // NULL -> ERROR + error =ffs_initialize(); + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_INIT()\n")); + ttw(ttr(TTrTmffs, "tm_init" NL)); + break; + case FPI_EXIT: + // NULL -> ERROR + error = ffs_exit(); + tmffs_put8(error); + tw(tr(TR_FUNC, TrTmffs, "FPI_EXIT()\n")); + ttw(ttr(TTrTmffs, "tm_exit" NL)); + break; + + + case FPI_TFFS: + { + // STRING -> ERROR +#if (WITH_TFFS == 1) + extern char ffs_test_string[]; // defined in task.c + + memcpy(ffs_test_string, string, stringsize); + tw(tr(TR_FUNC, TrTmffs, "FPI_TFFS()\n")); + ttw(ttr(TTrTmffs, "tm_tffs" NL)); +#else + tmffs_put8(EFFS_NOSYS); +#endif + break; + } + default: + tw(tr(TR_FUNC, TrTmffs, "ERROR: Unknown tmffs protocol code\n")); + ttw(ttr(TTrTmffs, "tm?" NL)); + break; + } + // check if we read beyond buffer end + if (inp > inp_start + insize) { + tw(tr(TR_FUNC, TrTmffs, "ERROR: Read beyond end of input buffer\n")); + ttw(ttr(TTrTmffs, "tm_fatal" NL)); + // NOTEME: We really should reset output buffer and put a return + // code that tells us what went wrong! + return 0; + } + } + + tw(tr(TR_END, TrTmffs, "")); + + return outp - outp_start; +} + +int tmffs_bufsize(void) +{ + return TMFFS1_BUFFER_SIZE; +} + +unsigned char *tmffs_bufaddr(void) +{ + return buffer; +} + +#endif // TMFFS1 + +/****************************************************************************** + * FFS2 protocol + ******************************************************************************/ + +#ifndef TMFFS2 + +#ifdef RVM_ETM_SWE +int etm_ffs2(T_ETM_PKT *pkt, unsigned char *inp, int insize) +{ + int error; + + tw(tr(TR_BEGIN, TrTmffs, "FFS2 protocol not represented in target\n")); + error = -1; // FIXME other error? + + // We return a packet instead of waiting for timeout. + pkt->size = 0; + pkt->status = -error; + pkt->mid = ETM_FFS2; + etm_pkt_send(pkt); + + target_free(pkt); + tw(tr(TR_END, TrTmffs, "")); + + return error; +} +#endif + +#else + +#define TMFFS_BUFFER_SIZE 256 // FIXME change to packet size +#define TMFFS_STRING_SIZE 127 + +/****************************************************************************** + * Macros + ******************************************************************************/ + +#define tmffs_get8() inp[0]; inp += 1; +#define tmffs_get16() (inp[0]) | (inp[1] << 8); inp += 2; +#define tmffs_get32() inp[0] | (inp[1] << 8) | (inp[2] << 16)\ + | (inp[3] << 24); inp += 4; + +#define tmffs_getdata() bufsize = inp[0]; inp += 1; \ + memcpy(buffer, inp, bufsize); inp += bufsize; + + +/****************************************************************************** + * Helper function + ******************************************************************************/ + +// If size is less than zero it is because of a error and we dont have to put any +// data if size is returned in status. +int tmffs_putdata(unsigned char **buf, unsigned char *src, int size) +{ + unsigned char *p = *buf; + + if (size > 0) { + *p++ = size; + memcpy(p, src, size); + *buf += 1 + size; + } + return size; +} + +int tmffs_putstring(unsigned char **buf, char *src, int size) +{ + unsigned char *p = *buf; + + if (size > 0) { + *p++ = size; + memcpy(p, src, size); + *buf += 1 + size; + } + return size; +} + +int tmffs_getstring(unsigned char ** buf, char *string) +{ + unsigned char *p = *buf; + + stringsize = *p++; + + if (stringsize > TMFFS_STRING_SIZE) + return EFFS_TOOBIG; + + memcpy(string, p, stringsize); + *buf += 1 + stringsize; + + return stringsize; +} + +/****************************************************************************** + * tm_ffs + ******************************************************************************/ + +// Parse input message and execute function. Then fill output buffer with +// return values from the called function and transmit the message. Return +// number of bytes inserted into output buffer. If return value is negative, +// it represents an error code. +int etm_ffs2(T_ETM_PKT *pkt, unsigned char *inp, int insize) +{ + tmffs2_cid_t fid; + unsigned char buffer[TMFFS_BUFFER_SIZE]; + char string[TMFFS_STRING_SIZE]; + + unsigned char *outp_start; + unsigned char *inp_start = inp; + unsigned char *outp; + + int error = 0, i, fdi, size, param, flags; + uint8 type; + + bufsize = stringsize = tmpsize = 0; + + tw(tr(TR_BEGIN, TrTmffs, "TmFFS2\n")); + + outp_start = outp = pkt->data; + + fid = *inp++; + ttw(ttr(TTrTmffs, "etm_ffs2 0x%x" NL, fid)); + switch(fid) + { + /********************************************************** + * Generic Protocol Functions + **********************************************************/ + + case TMFFS_VERSION: + tmffs_put16(TMFFS2_VERSION); + break; + + /********************************************************** + * FFS Functions + **********************************************************/ + + case TMFFS_PREFORMAT: + param = tmffs_get16(); + error = ffs_preformat(param); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_PREFORMAT(0x%x)\n", param)); + ttw(ttr(TTrTmffs, "tm_pfmt" NL)); + break; + case TMFFS_FORMAT: + error = tmffs_getstring(&inp, string); + param = tmffs_get16(); + if (error >= 0) + error = ffs_format(&string[0], param); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_FORMAT(0x%x)\n", param)); + ttw(ttr(TTrTmffs, "tm_fmt" NL)); + break; + + + case TMFFS_FILE_WRITE: + error = tmffs_getstring(&inp, string); + tmffs_getdata(); + flags = tmffs_get8(); + if (error >= 0) + error = ffs_file_write(string, buffer, bufsize, flags); + ttw(ttr(TTrTmffs, "tm_fwr" NL)); + break; + + + case TMFFS_FILE_READ: + error = tmffs_getstring(&inp, string); + bufsize = tmffs_get8(); + if (error >= 0) + size = ffs_file_read(string, buffer, bufsize); + error = tmffs_putdata(&outp, &buffer[0], size); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_FREAD('%s', 0x%x, %d/0x%x)\n", + string, buffer, bufsize, bufsize)); + ttw(ttr(TTrTmffs, "tm_frd" NL)); + break; + case TMFFS_REMOVE: + error = tmffs_getstring(&inp, string); + if (error >= 0) + error = ffs_remove(string); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_REMOVE()\n")); + ttw(ttr(TTrTmffs, "tm_rm" NL)); + break; + + + case TMFFS_OPEN: + error = tmffs_getstring(&inp, string); + flags = tmffs_get8(); + if (error >= 0) + error = ffs_open(string, flags); + tmffs_put8(error); // fdi + tw(tr(TR_FUNC, TrTmffs, "TMFFS_OPEN('%s', %d)\n", string, flags)); + ttw(ttr(TTrTmffs, "tm_open" NL)); + break; + case TMFFS_CLOSE: + fdi = tmffs_get8(); + error = ffs_close(fdi); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_CLOSE(%d)\n", fdi)); + ttw(ttr(TTrTmffs, "tm_close" NL)); + break; + case TMFFS_WRITE: + fdi = tmffs_get8(); + tmffs_getdata(); + error = ffs_write(fdi, buffer, bufsize); + tmffs_put8(error); // put size + tw(tr(TR_FUNC, TrTmffs, "TMFFS_WRITE(%d, %d)\n", fdi, bufsize)); + ttw(ttr(TTrTmffs, "tm_write" NL)); + break; + case TMFFS_READ: + fdi = tmffs_get8(); + size = tmffs_get8(); + size = ffs_read(fdi, &buffer[0], size); + error = tmffs_putdata(&outp, &buffer[0], size); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_READ(%d, %d)\n", fdi, size)); + ttw(ttr(TTrTmffs, "tm_read" NL)); + break; + + + case TMFFS_MKDIR: + error = tmffs_getstring(&inp, string); + if (error >= 0) + error = ffs_mkdir(string); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_MKDIR()\n")); + ttw(ttr(TTrTmffs, "tm_mkd" NL)); + break; + case TMFFS_OPENDIR: + error = tmffs_getstring(&inp, string); + if (error >= 0) { + error = ffs_opendir(string, (struct dir_s *) buffer); + tmffs_put8(error); // Note: we must put error/number of objects. + } + if (error >= 0) + tmffs_putdata(&outp, buffer, sizeof(struct dir_s)); + + tw(tr(TR_FUNC, TrTmffs, "TMFFS_OPENDIR()\n")); + ttw(ttr(TTrTmffs, "tm_od" NL)); + break; + case TMFFS_READDIR: + tmffs_getdata(); + stringsize = tmffs_get8(); + error = ffs_readdir((struct dir_s *) buffer, string, stringsize); + tmffs_put8(error); // Note: we have to return bytes read. + if (error >= 0) { + tmffs_putdata(&outp, buffer, sizeof(struct dir_s)); + stringsize = strlen(string) + 1; + tmffs_putstring(&outp, string, stringsize); + } + tw(tr(TR_FUNC, TrTmffs, "TMFFS_READDIR()\n")); + ttw(ttr(TTrTmffs, "tm_rdd" NL)); + break; + + case TMFFS_STAT: + error = tmffs_getstring(&inp, string); + if (error >= 0) + error = ffs_stat(string, (struct stat_s *) buffer); + if (error >= 0) + tmffs_putdata(&outp, buffer, sizeof(struct stat_s)); + + tw(tr(TR_FUNC, TrTmffs, "TMFFS_STAT()\n")); + ttw(ttr(TTrTmffs, "tm_st" NL)); + break; + case TMFFS_XLSTAT: + error = tmffs_getstring(&inp, string); + if (error >= 0) + error = ffs_xlstat(&string[0], (struct xstat_s *) buffer); + if (error >= 0) + tmffs_putdata(&outp, buffer, sizeof(struct xstat_s)); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_()\n")); + ttw(ttr(TTrTmffs, "tm_xlst" NL)); + break; + + + case TMFFS_SYMLINK: + error = tmffs_getstring(&inp, string); + tmffs_getdata(); + if (error >= 0) + error = ffs_symlink(string, (char *) buffer); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_SYMLINK()\n")); + ttw(ttr(TTrTmffs, "tm_sym" NL)); + break; + case TMFFS_READLINK: + error = tmffs_getstring(&inp, string); + tmffs_getdata(); + if (error >= 0) { + size = ffs_readlink(string, (char *) buffer, TMFFS_BUFFER_SIZE); + error = tmffs_putdata(&outp, buffer, size); // put link contents + } + tw(tr(TR_FUNC, TrTmffs, "TMFFS_READLINK()\n")); + ttw(ttr(TTrTmffs, "tm_rdl" NL)); + break; + + + case TMFFS_QUERY: + param = tmffs_get8(); + error = ffs_query(param, buffer); + if (error >= 0) + tmffs_putdata(&outp, buffer, 16); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_QUERY(%d)\n", param)); + ttw(ttr(TTrTmffs, "tm_q" NL)); + break; + case TMFFS_FCONTROL: + error = tmffs_getstring(&inp, string); + type = tmffs_get8(); + param = tmffs_get32(); + if (error >= 0) + error = ffs_fcontrol(string, type, param); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_FCONTROL()\n")); + ttw(ttr(TTrTmffs, "tm_fc" NL)); + break; + + case TMFFS_TFFS: + { +#if (WITH_TFFS == 1) + extern char ffs_test_string[]; // defined in task.c + error = tmffs_getstring(&inp, string); + memcpy(ffs_test_string, string, stringsize); + tw(tr(TR_FUNC, TrTmffs, "TMFFS_TFFS()\n")); + ttw(ttr(TTrTmffs, "tm_tffs" NL)); + tmffs_put8(EFFS_OK); +#else + tmffs_put8(EFFS_NOSYS); +#endif + break; + } + default: + error = EFFS_NOSYS; + tmffs_put8(EFFS_NOSYS); + tw(tr(TR_FUNC, TrTmffs, "ERROR: Unknown tmffs protocol code\n")); + ttw(ttr(TTrTmffs, "tm?" NL)); + break; + } + + // check if we read beyond buffer end + if (inp > inp_start + insize) { + tw(tr(TR_FUNC, TrTmffs, "ERROR: Read beyond end of input buffer\n")); + ttw(ttr(TTrTmffs, "tm_fatal" NL)); + ttw(ttr(TTrTmffs, "insize: %d, diff: %d" NL, insize, + inp - (inp_start + insize))); + // NOTEME: We really should reset output buffer and put a return + // code that tells us what went wrong! + error = ETM_PACKET; // FIXME find another error + } + + ttw(ttr(TTrTmffs, "error %d" NL, error)); + if (error > 0) + error = 0; + + pkt->mid = ETM_FFS2; + pkt->size = outp - outp_start; + pkt->status = -error; + + etm_pkt_send(pkt); + etm_free(pkt); + + tw(tr(TR_END, TrTmffs, "")); + + return ETM_OK; +} + +#endif // TMFFS2