PageRenderTime 86ms CodeModel.GetById 2ms app.highlight 70ms RepoModel.GetById 1ms app.codeStats 0ms

/peek-build/m23/csw-system/drv_app/ffs/board/tmffs.c

https://bitbucket.org/C0deMaver1ck/peeklinux
C | 959 lines | 698 code | 136 blank | 125 comment | 89 complexity | 6ceb05781fa1e2295df8052edcb2b2f2 MD5 | raw file
  1/******************************************************************************
  2 * Flash File System (ffs)
  3 * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
  4 *
  5 * ffs testmode interface
  6 *
  7 * $Id: tmffs.c 1.51 Thu, 18 Dec 2003 10:50:52 +0100 tsj $
  8 *
  9 ******************************************************************************/
 10
 11#ifndef TARGET
 12#include "ffs.cfg"
 13#endif
 14
 15#if (TARGET == 1)
 16#include "etm/etm.h"
 17#include "etm/etm_api.h"
 18#include "ffs/board/task.h"
 19#endif
 20
 21#include "ffs/board/ffstrace.h"
 22#include "ffs/board/tmffs.h"
 23#include "ffs/ffs_api.h"
 24#include "ffs/pcm.h"
 25#include "swconfig.cfg"
 26
 27#include <string.h>
 28
 29/******************************************************************************
 30 * Local globals for all protocols
 31 ******************************************************************************/
 32
 33static int32 bufsize, tmpsize;
 34static uint8 stringsize;
 35
 36effs_t ffs_initialize(void);
 37effs_t ffs_exit(void);
 38
 39#define tmffs_put8(x)   *outp++ = x;
 40#define tmffs_put16(x) *outp++ = (x & 0xff); *outp++ = (x>>8);
 41
 42#if (TARGET == 1)
 43int etm_ffs2(T_ETM_PKT *pkt, unsigned char *inp, int insize);
 44
 45// Not in use
 46//#define tmffs_put32(x) tmffs_put16(x); tmffs_put16(x >> 16);
 47
 48
 49/******************************************************************************
 50 * TM FFS registration to ETM database
 51 *****************************************************************************/
 52/* Callback function registered in ETM database */
 53int etm_ffs1_pkt_receive(uint8 *data, int size)
 54{
 55    int mid;
 56    T_ETM_PKT *pkt;  
 57
 58    ttw(ttr(TTrTmffs, "etm_ffs1_pkt_receive(*, %d)" NL, size)); 
 59    
 60    /* Create TestMode return Packet */
 61    if ((pkt = (T_ETM_PKT *) target_malloc(sizeof(T_ETM_PKT))) == NULL) {
 62        ttw(ttr(TTrTmffs, "etm_ffs1_pkt_receive(): Limit of memory bank reached" NL)); 
 63        return ETM_NOMEM;
 64    }
 65 
 66    // Max packet size for TM3 is 128 bytes
 67    size = tm_ffs(pkt->data, TM3_PACKET_SIZE, data, size);
 68
 69    pkt->size   = size;
 70    pkt->status = ETM_OK;
 71    pkt->mid    = ETM_FFS1;
 72    
 73    etm_pkt_send(pkt);
 74    target_free(pkt);
 75
 76    return ETM_OK;
 77}
 78
 79/* Callback function registered in ETM database */
 80int etm_ffs2_pkt_receive(uint8 *data, int size)
 81{
 82    int status;
 83    T_ETM_PKT *pkt = NULL;  
 84
 85    ttw(ttr(TTrTmffs, "etm_ffs2_pkt_receive(*, %d)" NL, size)); 
 86
 87    /* Create TestMode return Packet */
 88    if ((pkt = (T_ETM_PKT *) target_malloc(sizeof(T_ETM_PKT))) == NULL) {
 89        ttw(ttr(TTrTmffs, "etm_ffs2_pkt_receive(): Limit of memory bank reached" NL)); 
 90        return ETM_NOMEM;
 91    } 
 92    
 93    status = etm_ffs2(pkt, data, size);
 94    return status;
 95}
 96
 97/* Init of FFS in the ETM database */
 98int etm_ffs_init(void)
 99{
100    int status;
101    
102    status = etm_register("FFS1", ETM_FFS1, 0, 0, etm_ffs1_pkt_receive);
103    status = etm_register("FFS2", ETM_FFS2, 0, 0, etm_ffs2_pkt_receive);
104    return status;
105} 
106#endif // (TARGET == 1)
107
108/******************************************************************************
109 * FFS1 Protocol 
110 ******************************************************************************/
111
112#ifndef TMFFS1 
113
114int tm_ffs(unsigned char *outp, int outsize, unsigned char *inp, int insize)
115{
116	return -1;   // FIXME handle error better 
117}
118
119// Note these functions must be presented because ffs_query() use them but
120// they are only valid if FFS1_PROTOCOL is used.
121int tmffs_bufsize(void)
122{
123    return EFFS_NOSYS;
124}
125
126unsigned char *tmffs_bufaddr(void)
127{
128    return 0;
129}
130
131#else
132
133#define TMFFS1_BUFFER_SIZE 8192 
134
135#define TMFFS1_STRING_SIZE 127
136
137/******************************************************************************
138 * Macros
139 ******************************************************************************/
140
141#define tmffs1_putdata(outp, src, size) \
142    tmffs_put8(FPI_DATA); \
143    tmffs_put16(size); \
144    memcpy(outp, src, size); \
145    outp += size;
146
147/******************************************************************************
148 * Local globals
149 ******************************************************************************/
150
151static unsigned char buffer[TMFFS1_BUFFER_SIZE];
152static bufindex;
153
154static char string[TMFFS1_STRING_SIZE];
155
156static effs_t tm_ffs_overflowck(void)
157{
158    if (bufsize    > TMFFS1_BUFFER_SIZE ||
159        stringsize > TMFFS1_STRING_SIZE)
160        return EFFS_TOOBIG;
161
162    return EFFS_OK;
163}
164
165
166/******************************************************************************
167 * tm_ffs
168 ******************************************************************************/
169
170/**
171 * NOTEME: This has been introduced when the ffs 1MB device limit was
172 * broken. This made location_t go from uint16 to uint32, messing up
173 * with PCTM.  
174 *
175 * This makes the xstat_s look the same to PCTM PC side, though
176 * location will be forced to 0.
177 */
178void hack_xstat_2_look_like_old_xstat(struct xstat_s *xstat)
179{
180  int i;
181  char *location;
182
183  xstat->location = 0;
184  
185  for (location = (char *) &(xstat->location) + 2; location <= (char *) &(xstat->sequence); location++)
186    *location = location[2];
187}
188
189// Parse input message and execute function. Then fill output buffer with
190// return values from the called function and transmit the message.  Return
191// number of bytes inserted into output buffer. If return value is negative,
192// it represents an error code.
193int tm_ffs(unsigned char *outp, int outsize, unsigned char *inp, int insize)
194{
195    int error;
196    tmffs_cid_t fid;
197
198    unsigned char *outp_start = outp;
199    unsigned char *inp_start  = inp;
200
201    static uint8   i8[2]; static uint16 i8i;
202    static uint16 i16[2]; static uint16 i16i;
203    static uint32 i32[2]; static uint16 i32i;
204
205    tw(tr(TR_BEGIN, TrTmffs, "TMFFS:\n"));
206
207    while((fid = *inp++) != FPI_END)
208    {
209        switch(fid)
210        {
211            /**********************************************************
212             * Generic Protocol Functions
213             **********************************************************/
214
215        case FPI_BEGIN:
216            // for (i8i = 0; i8i < TMFFS1_STRING_SIZE; i8i++) // DEBUG
217            //     string[i8i] = '#';
218            // for (i8i = 0; i8i < TMFFS1_BUFFER_SIZE; i8i++) // DEBUG
219            //     buffer[i8i] = '$';
220            i8i = i16i = i32i = bufsize = stringsize = 0;
221            bufindex = 0;
222             i8[0] =  i8[1] = 0;
223            i16[0] = i16[1] = 0;
224            i32[0] = i32[1] = 0;
225            string[0] = buffer[0] = 0;
226            tw(tr(TR_FUNC, TrTmffs, "FPI_BEGIN\n"));
227            ttw(ttr(TTrTmffs, "tm1" NL));
228            break;
229        case FPI_TMFFS_VERSION:
230            // NULL -> UINT16
231            tmffs_put16(TMFFS1_VERSION);
232            break;
233
234        case FPI_INT8:
235            i8[i8i++] = inp[0]; inp += 1;
236            tw(tr(TR_FUNC, TrTmffs, "FPI_INT8(%d/0x%x)\n",
237                  i8[i8i-1], i8[i8i-1]));
238            ttw(ttr(TTrTmffs, "tm_i8" NL));
239            break;
240        case FPI_INT16:
241            i16[i16i++] = (inp[0]) | (inp[1] << 8); inp += 2;
242            tw(tr(TR_FUNC, TrTmffs, "FPI_INT16(%d/0x%x)\n",
243                  i16[i16i-1], i16[i16i-1]));
244            ttw(ttr(TTrTmffs, "tm_i16" NL));
245            break;
246        case FPI_INT32:
247            i32[i32i++] = inp[0] | (inp[1] << 8)
248                | (inp[2] << 16) | (inp[3] << 24);
249            inp += 4;
250            tw(tr(TR_FUNC, TrTmffs, "FPI_INT32(%d/0x%x)\n",
251                  i32[i32i-1], i32[i32i-1]));
252            ttw(ttr(TTrTmffs, "tm_i32" NL));
253            break;
254        case FPI_BUFFER:
255            bufsize = inp[0] | (inp[1] << 8); inp += 2;
256            tw(tr(TR_FUNC, TrTmffs, "FPI_BUFFER(%d)\n", bufsize));
257            ttw(ttr(TTrTmffs, "tm_buf" NL));
258            break;
259        case FPI_DATA:
260            bufsize = inp[0] | (inp[1] << 8); inp += 2;
261            memcpy(buffer, inp, bufsize); inp += bufsize;
262            tw(tr(TR_FUNC, TrTmffs, "FPI_DATA(%d)\n", bufsize));
263            ttw(ttr(TTrTmffs, "tm_data" NL));
264            break;
265        case FPI_STRBUF:
266            // string buffer size MUST include null-terminator!
267            stringsize = inp[0]; inp += 1;
268            tw(tr(TR_FUNC, TrTmffs, "FPI_STRBUF(%d)\n", stringsize));
269            ttw(ttr(TTrTmffs, "tm_sbuf" NL));
270            break;
271        case FPI_STRING:
272            // stringsize MUST include null-terminator!
273            // <INT8>, <BYTES> -> NULL (or ERROR)
274            stringsize = inp[0]; inp += 1;
275            if (stringsize <= TMFFS1_STRING_SIZE)
276                memcpy(string, inp, stringsize);
277            inp += stringsize;
278            tw(tr(TR_FUNC, TrTmffs, "FPI_STRING(%d,'%s')\n",
279                  stringsize, string));
280            ttw(ttr(TTrTmffs, "tm_s" NL));
281            break;
282
283        case FPI_BUFREAD:
284            // <INT16> -> DATA
285            tmpsize = inp[0] | (inp[1] << 8); inp += 2;
286            tw(tr(TR_FUNC, TrTmffs, "FPI_BUF_READ(%d)\n", tmpsize));
287            tmffs1_putdata(outp, &buffer[bufindex], tmpsize);
288            bufindex += tmpsize;
289            ttw(ttr(TTrTmffs, "tm_bufrd" NL));
290            break;
291        case FPI_BUFWRITE:
292            // <INT16>, <BYTES> -> NULL (or ERROR)
293            tmpsize = inp[0] | (inp[1] << 8); inp += 2;
294            tw(tr(TR_FUNC, TrTmffs, "FPI_BUF_WRITE(%d)\n", tmpsize));
295            if (bufsize + tmpsize <= TMFFS1_BUFFER_SIZE)
296                memcpy(&buffer[bufsize], inp, tmpsize);
297            inp += tmpsize;
298            bufsize += tmpsize;
299            ttw(ttr(TTrTmffs, "tm_bufwr" NL));
300            break;
301        case FPI_BUFSET:
302            bufindex = inp[0] | (inp[1] << 8); inp += 2;
303            tw(tr(TR_FUNC, TrTmffs, "FPI_BUF_SET(%d)\n", bufindex));
304            ttw(ttr(TTrTmffs, "tm_bufset" NL));
305            break;
306
307            /**********************************************************
308             * FFS Functions
309             **********************************************************/
310
311        case FPI_PREFORMAT:
312            // NULL -> ERROR
313            if ((error = tm_ffs_overflowck()) == EFFS_OK)
314                error = ffs_preformat_nb(i16[0], 0);
315            if (error > 0) 
316                error = 0;  // ignore request id
317            tmffs_put8(error);
318            tw(tr(TR_FUNC, TrTmffs, "FPI_PREFORMAT(0x%x)\n", i16[0]));
319            ttw(ttr(TTrTmffs, "tm_pfmt" NL));
320            break;
321        case FPI_FORMAT:
322            // STRING -> ERROR
323            if ((error = tm_ffs_overflowck()) == EFFS_OK)
324                error = ffs_format_nb(&string[0], i16[0], 0);
325            if (error > 0) 
326                error = 0;  // ignore request id
327            tmffs_put8(error);
328            tw(tr(TR_FUNC, TrTmffs, "FPI_FORMAT(0x%x)\n", i16[0]));
329            ttw(ttr(TTrTmffs, "tm_fmt" NL));
330            break;
331
332
333        case FPI_FCREATE:
334            // STRING, DATA -> ERROR
335            if ((error = tm_ffs_overflowck()) == EFFS_OK)
336                error = ffs_file_write_nb(string, buffer, bufsize, 
337                                          FFS_O_CREATE | FFS_O_EXCL, 0);
338            if (error > 0) 
339                error = 0;  // ignore request id
340            tmffs_put8(error);
341            tw(tr(TR_FUNC, TrTmffs, "FPI_FCREATE('%s', 0x%x, %d/0x%x)\n",
342                  string, buffer, bufsize, bufsize));
343            ttw(ttr(TTrTmffs, "tm_fcr" NL));
344            break;
345        case FPI_FUPDATE:
346            // STRING, DATA -> ERROR
347            if ((error = tm_ffs_overflowck()) == EFFS_OK)
348                error = ffs_file_write_nb(string, buffer, bufsize, FFS_O_TRUNC, 0);
349            if (error > 0) 
350                error = 0;  // ignore request id
351            tmffs_put8(error);
352            tw(tr(TR_FUNC, TrTmffs, "FPI_FUPDATE('%s', 0x%x, %d/0x%x)\n",
353                  string, buffer, bufsize, bufsize));
354            ttw(ttr(TTrTmffs, "tm_fup" NL));
355            break;
356        case FPI_FWRITE:
357            // STRING, DATA -> ERROR
358            if ((error = tm_ffs_overflowck()) == EFFS_OK)
359                error = ffs_file_write_nb(string, buffer, bufsize, 
360                                      FFS_O_CREATE | FFS_O_TRUNC, 0);
361            if (error > 0) 
362                error = 0;  // ignore request id
363            tmffs_put8(error);
364            tw(tr(TR_FUNC, TrTmffs, "FPI_FWRITE('%s', 0x%x, %d/0x%x)\n",
365                  string, buffer, bufsize, bufsize));
366            ttw(ttr(TTrTmffs, "tm_fwr" NL));
367            break;
368        case FPI_FREAD:
369            // STRING, BUFFER -> ERROR
370            if ((error = tm_ffs_overflowck()) == EFFS_OK)
371                error = ffs_file_read(string, buffer, TMFFS1_BUFFER_SIZE);
372            // Because a 32-bit integer is returned, we have to saturate it
373            // into an 8-bit value.
374            if (error >= 0)
375                error = 0;
376            tmffs_put8(error);
377            tw(tr(TR_FUNC, TrTmffs, "FPI_FREAD('%s', 0x%x, %d/0x%x)\n",
378                  string, buffer, bufsize, bufsize));
379            ttw(ttr(TTrTmffs, "tm_frd" NL));
380            break;
381        case FPI_REMOVE:
382            // STRING -> ERROR
383            if ((error = tm_ffs_overflowck()) == EFFS_OK)
384                error = ffs_remove_nb(string, 0);
385            if (error > 0) 
386                error = 0;  // ignore request id
387            tmffs_put8(error);
388            tw(tr(TR_FUNC, TrTmffs, "FPI_REMOVE()\n"));
389            ttw(ttr(TTrTmffs, "tm_rm" NL));
390            break;
391
392
393        case FPI_MKDIR:
394            // STRING -> ERROR
395            if ((error = tm_ffs_overflowck()) == EFFS_OK)
396                error = ffs_mkdir_nb(string, 0);
397            if (error > 0) 
398                error = 0;  // ignore request id
399            tmffs_put8(error);
400            tw(tr(TR_FUNC, TrTmffs, "FPI_MKDIR()\n"));
401            ttw(ttr(TTrTmffs, "tm_mkd" NL));
402            break;
403        case FPI_OPENDIR:
404            // STRING, BUFFER -> ERROR, DATA
405            if ((error = tm_ffs_overflowck()) == EFFS_OK)
406                error = ffs_opendir(string, (struct dir_s *) buffer);
407            // Because a 32-bit integer is returned, we have to saturate it
408            // into an 8-bit value.
409            if (error >= 0)
410                error = 0;
411            tmffs_put8(error);
412            tmffs1_putdata(outp, buffer, sizeof(struct dir_s));
413            tw(tr(TR_FUNC, TrTmffs, "FPI_OPENDIR()\n"));
414            ttw(ttr(TTrTmffs, "tm_od" NL));
415            break;
416        case FPI_READDIR:
417            // DATA, STRBUF -> ERROR, DATA, STRING
418            string[0] = 0;
419            if ((error = tm_ffs_overflowck()) == EFFS_OK)
420                error = ffs_readdir((struct dir_s *) buffer, string, stringsize);
421
422			// Saturate error(i) in order to let it fit in type int8.
423			if (error > 127)
424				error = 127;
425            tmffs_put8(error);
426            tmffs1_putdata(outp, buffer, sizeof(struct dir_s));
427            stringsize = strlen(string) + 1;
428            tmffs_put8(FPI_STRING); // put directory entry's name...
429            tmffs_put8(stringsize);
430            memcpy(outp, string, stringsize);
431            outp += stringsize;
432            tw(tr(TR_FUNC, TrTmffs, "FPI_READDIR()\n"));
433            ttw(ttr(TTrTmffs, "tm_rdd" NL));
434            break;
435
436
437        case FPI_STAT:
438            // STRING, BUFFER -> ERROR, DATA 
439            if ((error = tm_ffs_overflowck()) == EFFS_OK)
440                error = ffs_stat(&string[0], (struct stat_s *) buffer);
441            tmffs_put8(error);
442            tmffs1_putdata(outp, buffer, sizeof(struct stat_s));
443            tw(tr(TR_FUNC, TrTmffs, "FPI_STAT()\n"));
444            ttw(ttr(TTrTmffs, "tm_st" NL));
445            break;
446        case FPI_LINKSTAT:
447            // STRING, BUFFER -> ERROR, DATA
448            if ((error = tm_ffs_overflowck()) == EFFS_OK)
449                error = ffs_xlstat(&string[0], (struct xstat_s *) buffer);
450            tmffs_put8(error);
451
452            hack_xstat_2_look_like_old_xstat((struct xstat_s *) buffer);
453
454            tmffs1_putdata(outp, buffer, sizeof(struct xstat_s) - 2);
455            tw(tr(TR_FUNC, TrTmffs, "FPI_()\n"));
456            ttw(ttr(TTrTmffs, "tm_lst" NL));
457            break;
458
459
460        case FPI_SYMLINK:
461            // STRING, DATA -> ERROR
462            if ((error = tm_ffs_overflowck()) == EFFS_OK)
463                error = ffs_symlink_nb(string, (char *) buffer, 0);
464            if (error > 0) 
465                error = 0;  // ignore request id
466            tmffs_put8(error);
467            tw(tr(TR_FUNC, TrTmffs, "FPI_SYMLINK()\n"));
468            ttw(ttr(TTrTmffs, "tm_sym" NL));
469            break;
470        case FPI_READLINK:
471            // STRING, BUFFER -> ERROR, DATA
472            if ((error = tm_ffs_overflowck()) == EFFS_OK)
473                error = ffs_readlink(string, (char *) buffer, TMFFS1_BUFFER_SIZE);
474            // Because a 32-bit integer is returned, we have to saturate it
475            // into an 8-bit value.
476            if (error >= 0)
477                error = 0;
478            tmffs_put8(error);
479            tmffs1_putdata(outp, buffer, bufsize); // put link contents
480            tw(tr(TR_FUNC, TrTmffs, "FPI_READLINK()\n"));
481            ttw(ttr(TTrTmffs, "tm_rdl" NL));
482            break;
483
484
485        case FPI_QUERY:
486            // INT8 -> ERROR, DATA
487            error = ffs_query(i8[0], buffer);
488            tmffs_put8(error);
489            tmffs1_putdata(outp, buffer, 16);
490            tw(tr(TR_FUNC, TrTmffs, "FPI_QUERY()\n"));
491            ttw(ttr(TTrTmffs, "tm_q" NL));
492            break;
493        case FPI_FCONTROL:
494            // STRING INT8 INT32 -> ERROR
495            if ((error = tm_ffs_overflowck()) == EFFS_OK)
496                error = ffs_fcontrol_nb(string, i8[0], i32[0], 0);
497            if (error > 0) 
498                error = 0;  // ignore request id
499            tmffs_put8(error);
500            tw(tr(TR_FUNC, TrTmffs, "FPI_FCONTROL()\n"));
501            ttw(ttr(TTrTmffs, "tm_fc" NL));
502            break;
503
504        case FPI_INIT:
505            // NULL -> ERROR
506            error =ffs_initialize();
507            tmffs_put8(error);
508            tw(tr(TR_FUNC, TrTmffs, "FPI_INIT()\n"));
509            ttw(ttr(TTrTmffs, "tm_init" NL));
510            break;
511        case FPI_EXIT:
512            // NULL -> ERROR
513            error = ffs_exit();
514            tmffs_put8(error);
515            tw(tr(TR_FUNC, TrTmffs, "FPI_EXIT()\n"));
516            ttw(ttr(TTrTmffs, "tm_exit" NL));
517            break;
518
519
520        case FPI_TFFS:
521        {
522            // STRING -> ERROR
523#if (WITH_TFFS == 1)
524            extern char ffs_test_string[]; // defined in task.c
525
526            memcpy(ffs_test_string, string, stringsize);
527            tw(tr(TR_FUNC, TrTmffs, "FPI_TFFS()\n"));
528            ttw(ttr(TTrTmffs, "tm_tffs" NL));
529#else
530            tmffs_put8(EFFS_NOSYS);
531#endif            
532            break;
533        }
534        default:
535            tw(tr(TR_FUNC, TrTmffs, "ERROR: Unknown tmffs protocol code\n"));
536            ttw(ttr(TTrTmffs, "tm?" NL));
537            break;
538        }
539        // check if we read beyond buffer end
540        if (inp > inp_start + insize) {
541            tw(tr(TR_FUNC, TrTmffs, "ERROR: Read beyond end of input buffer\n"));
542            ttw(ttr(TTrTmffs, "tm_fatal" NL));
543            // NOTEME: We really should reset output buffer and put a return
544            // code that tells us what went wrong!
545            return 0;
546        }
547    }
548
549    tw(tr(TR_END, TrTmffs, ""));
550
551    return outp - outp_start;
552}
553
554int tmffs_bufsize(void)
555{
556    return TMFFS1_BUFFER_SIZE;
557}
558
559unsigned char *tmffs_bufaddr(void)
560{
561    return buffer;
562}
563
564#endif // TMFFS1 
565
566/******************************************************************************
567 * FFS2 protocol  
568 ******************************************************************************/
569
570#ifndef TMFFS2
571
572#if (TARGET == 1)
573
574int etm_ffs2(T_ETM_PKT *pkt, unsigned char *inp, int insize)
575{
576	int error;
577
578	tw(tr(TR_BEGIN, TrTmffs, "FFS2 protocol not represented in target\n"));
579	error = -1;  // FIXME other error?
580
581#if 0  // Note we can only use this if etm is in target
582	// We return a packet instead of waiting for timeout.
583	pkt->size =  0;
584    pkt->status = -error;       
585    pkt->mid = ETM_FFS2;
586    etm_pkt_send(pkt);
587#endif
588
589    target_free(pkt);
590    tw(tr(TR_END, TrTmffs, ""));
591
592	return error;
593}
594
595#endif // (TARGET == 1)
596
597#else
598
599#define TMFFS_BUFFER_SIZE 256   // FIXME change to packet size
600#define TMFFS_STRING_SIZE 127
601
602/******************************************************************************
603 * Macros
604 ******************************************************************************/
605
606#define tmffs_get8() inp[0]; inp += 1; 
607#define tmffs_get16() (inp[0]) | (inp[1] << 8); inp += 2; 
608#define tmffs_get32()  inp[0] | (inp[1] << 8) | (inp[2] << 16)\
609                       | (inp[3] << 24); inp += 4; 
610
611#define tmffs_getdata()    bufsize = inp[0]; inp += 1; \
612                           memcpy(buffer, inp, bufsize); inp += bufsize;
613
614
615/******************************************************************************
616 * Helper function
617 ******************************************************************************/
618
619// If size is less than zero it is because of a error and we dont have to put any
620// data if size is returned in status.
621int tmffs_putdata(unsigned char **buf, unsigned char *src, int size) 
622{
623 	unsigned char *p = *buf;
624
625	if (size > 0) {
626		*p++ = size;
627		memcpy(p, src, size); 
628		*buf += 1 + size;
629	}
630	return size;
631}
632
633int tmffs_putstring(unsigned char **buf, char *src, int size) 
634{
635	unsigned char *p = *buf;
636
637	if (size > 0) {
638		*p++ = size;
639		memcpy(p, src, size); 
640		*buf += 1 + size;
641	}
642	return size;
643}
644
645int tmffs_getstring(unsigned char ** buf, char *string)
646{
647	unsigned char *p = *buf;
648	
649	stringsize = *p++;
650
651	if (stringsize > TMFFS_STRING_SIZE) 
652		return EFFS_TOOBIG;
653
654	memcpy(string, p, stringsize);
655	*buf += 1 + stringsize;
656
657	return stringsize;
658}
659
660#if (RELIANCE_FS==1)
661/* Mantain only one open directory at a time */
662char is_dir_open = 0;
663T_FFS_DIR dir_backup;
664#endif
665/******************************************************************************
666 * tm_ffs
667 ******************************************************************************/
668
669// Parse input message and execute function. Then fill output buffer with
670// return values from the called function and transmit the message.  Return
671// number of bytes inserted into output buffer. If return value is negative,
672// it represents an error code.
673int etm_ffs2(T_ETM_PKT *pkt, unsigned char *inp, int insize)
674{
675	tmffs2_cid_t fid;
676	unsigned char buffer[TMFFS_BUFFER_SIZE];
677	char string[TMFFS_STRING_SIZE];
678
679    unsigned char *outp_start;
680    unsigned char *inp_start  = inp;
681	unsigned char *outp;
682
683	int error = 0, i, fdi, size, param, flags;
684	uint8 type;
685
686	bufsize = stringsize = tmpsize = 0;
687
688	tw(tr(TR_BEGIN, TrTmffs, "TmFFS2\n"));
689    
690	outp_start = outp = pkt->data;
691	
692	  fid = (tmffs2_cid_t)*inp++;
693	ttw(ttr(TTrTmffs, "etm_ffs2 0x%x" NL, fid));
694	switch(fid)
695	{
696		/**********************************************************
697		 * Generic Protocol Functions
698		 **********************************************************/
699
700	case TMFFS_VERSION:
701		tmffs_put16(TMFFS2_VERSION);
702		break;
703
704		/**********************************************************
705		 * FFS Functions
706		 **********************************************************/
707
708	case TMFFS_PREFORMAT:
709		param = tmffs_get16();
710		error = ffs_preformat(param);	
711		tw(tr(TR_FUNC, TrTmffs, "TMFFS_PREFORMAT(0x%x)\n", param));
712		ttw(ttr(TTrTmffs, "tm_pfmt" NL));
713		break;
714	case TMFFS_FORMAT: 
715		error = tmffs_getstring(&inp, string);
716		param = tmffs_get16();
717		if (error >= 0)
718			error = ffs_format(&string[0], param);	
719		tw(tr(TR_FUNC, TrTmffs, "TMFFS_FORMAT(0x%x)\n", param));
720		ttw(ttr(TTrTmffs, "tm_fmt" NL));	
721		break;
722
723		
724	case TMFFS_FILE_WRITE:
725		error = tmffs_getstring(&inp, string);
726		tmffs_getdata();
727		flags = tmffs_get8();
728		if (error >= 0)
729			error = ffs_file_write(string, buffer, bufsize, flags);
730		ttw(ttr(TTrTmffs, "tm_fwr" NL));
731		break;
732
733
734	case TMFFS_FILE_READ:
735		error = tmffs_getstring(&inp, string);
736		bufsize = tmffs_get8();
737		if (error >= 0)
738			size = ffs_file_read(string, buffer, bufsize);
739		error = tmffs_putdata(&outp, &buffer[0], size);
740		tw(tr(TR_FUNC, TrTmffs, "TMFFS_FREAD('%s', 0x%x, %d/0x%x)\n",
741			  string, buffer, bufsize, bufsize));
742		ttw(ttr(TTrTmffs, "tm_frd" NL));
743		break;
744	case TMFFS_REMOVE:
745		error = tmffs_getstring(&inp, string);
746		if (error >= 0)
747			error = ffs_remove(string);
748		tw(tr(TR_FUNC, TrTmffs, "TMFFS_REMOVE()\n"));
749		ttw(ttr(TTrTmffs, "tm_rm" NL));
750		break;
751
752
753	case TMFFS_OPEN:
754		error = tmffs_getstring(&inp, string);
755		flags = tmffs_get8();
756		if (error >= 0)
757			error = ffs_open(string, flags);
758		tmffs_put8(error); // fdi
759		tw(tr(TR_FUNC, TrTmffs, "TMFFS_OPEN('%s', %d)\n", string, flags));
760		ttw(ttr(TTrTmffs, "tm_open" NL));
761		break;
762	case TMFFS_CLOSE:
763		fdi = tmffs_get8(); 
764		error = ffs_close(fdi);
765		tw(tr(TR_FUNC, TrTmffs, "TMFFS_CLOSE(%d)\n", fdi));
766		ttw(ttr(TTrTmffs, "tm_close" NL));
767		break;
768	case TMFFS_WRITE:
769		fdi = tmffs_get8(); 
770		tmffs_getdata(); 
771		error = ffs_write(fdi, buffer, bufsize);
772		tmffs_put8(error); // put size
773		tw(tr(TR_FUNC, TrTmffs, "TMFFS_WRITE(%d, %d)\n", fdi, bufsize));
774		ttw(ttr(TTrTmffs, "tm_write" NL));
775		break;
776	case TMFFS_READ:
777		fdi = tmffs_get8(); 
778		size = tmffs_get8();
779		size = ffs_read(fdi, &buffer[0], size);
780		error =	tmffs_putdata(&outp, &buffer[0], size);
781		tw(tr(TR_FUNC, TrTmffs, "TMFFS_READ(%d, %d)\n", fdi, size));
782		ttw(ttr(TTrTmffs, "tm_read" NL));
783		break;
784
785
786	case TMFFS_MKDIR:
787		error = tmffs_getstring(&inp, string);
788		if (error >= 0)
789			error = ffs_mkdir(string);
790		tw(tr(TR_FUNC, TrTmffs, "TMFFS_MKDIR()\n"));
791		ttw(ttr(TTrTmffs, "tm_mkd" NL));
792		break;
793	case TMFFS_OPENDIR:
794		error = tmffs_getstring(&inp, string);
795		if (error >= 0) { 
796                        #if (RELIANCE_FS==1)
797			if(is_dir_open)
798				{
799				  /* close the previous directory */
800				  error=ffs_closedir(&dir_backup);
801				  is_dir_open=0;
802				}
803                        #endif			
804			error = ffs_opendir(string, (struct dir_s *) buffer);
805                        #if (RELIANCE_FS==1)
806			if(error >= 0)
807				{
808				  is_dir_open=1;   /* Indicate that directory is already opened */
809				  memcpy(&dir_backup,buffer,sizeof(T_FFS_DIR));   /* Keep the backup now */
810				}
811                        #endif
812			tmffs_put8(error); // Note: we must put error/number of objects.
813		}
814		if (error >= 0)
815			tmffs_putdata(&outp, buffer, sizeof(struct dir_s));
816		
817		tw(tr(TR_FUNC, TrTmffs, "TMFFS_OPENDIR()\n"));
818		ttw(ttr(TTrTmffs, "tm_od" NL));
819		break;
820	case TMFFS_READDIR:
821		tmffs_getdata();
822		stringsize = tmffs_get8();		
823		error = ffs_readdir((struct dir_s *) buffer, string, stringsize);
824#if 	(RELIANCE_FS==1)
825		// ignore . and .. folder entries if reliance is being used.
826		if (strcmp(string, ".") == NULL) {
827			error = ffs_readdir(((T_FFS_DIR *) buffer), string, stringsize);
828			}
829		if (strcmp(string, "..") == NULL) {
830			error = ffs_readdir(((T_FFS_DIR *) buffer), string, stringsize);
831			}
832#endif
833		tmffs_put8(error); // Note: we have to return bytes read.
834		if (error >= 0) {
835                        #if (RELIANCE_FS==1)
836			if(error == 0 && is_dir_open)   /* last entry read */
837				{							/* and backup has some directory opened */
838				  is_dir_open=0;   /* Indicate that directory is already opened */
839				}
840                        #endif
841			tmffs_putdata(&outp, buffer, sizeof(struct dir_s));
842			stringsize = strlen(string) + 1;			
843			tmffs_putstring(&outp, string, stringsize);
844		}
845		tw(tr(TR_FUNC, TrTmffs, "TMFFS_READDIR()\n"));
846		ttw(ttr(TTrTmffs, "tm_rdd" NL));
847		break;
848
849	case TMFFS_STAT:
850		error = tmffs_getstring(&inp, string);
851		if (error >= 0) 
852			error = ffs_stat(string, (struct stat_s *) buffer);
853		if (error >= 0)
854			tmffs_putdata(&outp, buffer, sizeof(struct stat_s));
855		
856		tw(tr(TR_FUNC, TrTmffs, "TMFFS_STAT()\n"));
857		ttw(ttr(TTrTmffs, "tm_st" NL));
858		break;
859	case TMFFS_XLSTAT:
860		error = tmffs_getstring(&inp, string);
861		if (error >= 0)
862			error = ffs_xlstat(&string[0], (struct xstat_s *) buffer);
863		if (error >= 0)
864			tmffs_putdata(&outp, buffer, sizeof(struct xstat_s));
865		tw(tr(TR_FUNC, TrTmffs, "TMFFS_()\n"));
866		ttw(ttr(TTrTmffs, "tm_xlst" NL));
867		break;
868
869
870	case TMFFS_SYMLINK:
871		error = tmffs_getstring(&inp, string);
872		tmffs_getdata();
873		if (error >= 0)
874			error = ffs_symlink(string, (char *) buffer);
875		tw(tr(TR_FUNC, TrTmffs, "TMFFS_SYMLINK()\n"));
876		ttw(ttr(TTrTmffs, "tm_sym" NL));
877		break;
878	case TMFFS_READLINK:
879		error = tmffs_getstring(&inp, string);
880		tmffs_getdata();
881		if (error >= 0) {
882			size = ffs_readlink(string, (char *) buffer, TMFFS_BUFFER_SIZE);
883			error = tmffs_putdata(&outp, buffer, size); // put link contents
884		}
885		tw(tr(TR_FUNC, TrTmffs, "TMFFS_READLINK()\n"));
886		ttw(ttr(TTrTmffs, "tm_rdl" NL));
887		break;
888
889
890	case TMFFS_QUERY:
891		param = tmffs_get8();
892		error = ffs_query(param, buffer);
893		if (error >= 0)
894			tmffs_putdata(&outp, buffer, 16);
895		tw(tr(TR_FUNC, TrTmffs, "TMFFS_QUERY(%d)\n", param));
896		ttw(ttr(TTrTmffs, "tm_q" NL));
897		break;
898	case TMFFS_FCONTROL:
899		error = tmffs_getstring(&inp, string);
900		type = tmffs_get8();
901		param = tmffs_get32();
902		if (error >= 0)
903			error = ffs_fcontrol(string, type, param);
904		tw(tr(TR_FUNC, TrTmffs, "TMFFS_FCONTROL()\n"));
905		ttw(ttr(TTrTmffs, "tm_fc" NL));
906		break;
907
908	case TMFFS_TFFS:
909	{
910#if (WITH_TFFS == 1)
911		extern char ffs_test_string[]; // defined in task.c
912		error = tmffs_getstring(&inp, string);
913		memcpy(ffs_test_string, string, stringsize);
914		tw(tr(TR_FUNC, TrTmffs, "TMFFS_TFFS()\n"));
915		ttw(ttr(TTrTmffs, "tm_tffs" NL));
916		tmffs_put8(EFFS_OK);
917#else
918              error=EFFS_NOSYS;
919		tmffs_put8(error);
920#endif            
921		break;
922	}
923	default:
924		error = EFFS_NOSYS;
925		tmffs_put8(error);
926		tw(tr(TR_FUNC, TrTmffs, "ERROR: Unknown tmffs protocol code\n"));
927		ttw(ttr(TTrTmffs, "tm?" NL));
928		break;
929	}
930	
931	// check if we read beyond buffer end
932	if (inp > inp_start + insize) {
933		tw(tr(TR_FUNC, TrTmffs, "ERROR: Read beyond end of input buffer\n"));
934		ttw(ttr(TTrTmffs, "tm_fatal" NL));
935		ttw(ttr(TTrTmffs, "insize: %d, diff: %d" NL, insize, 
936				inp - (inp_start + insize)));
937		// NOTEME: We really should reset output buffer and put a return
938		// code that tells us what went wrong!
939		error = ETM_PACKET;  // FIXME find another error 
940	}
941
942	ttw(ttr(TTrTmffs, "error %d" NL, error));
943	if (error > 0)
944		error = 0;
945
946    pkt->mid    = ETM_FFS2;
947	pkt->size   = outp - outp_start;
948    pkt->status = -error;
949
950    etm_pkt_send(pkt);
951    etm_free(pkt);
952
953    tw(tr(TR_END, TrTmffs, ""));
954
955    return ETM_OK;
956}
957
958#endif // TMFFS2
959