FreeCalypso > hg > fc-magnetite
view src/cs/drivers/drv_app/ffs/board/tffs.c @ 638:cab2f315827e
FFS dev.c: added Spansion PL032J to the "generic" table
With the discovery of first GTM900 and then Tango, it now appears that
Openmoko was not the only manuf after all who kept TI's TCS211 firmware
largely intact (as opposed to changing it beyond all recognition like
Compal, Chi-Mei and BenQ did), thus we are now getting new "alien" targets
on which we reuse the original manuf's FFS with IMEI and RF calibration
tables as if it were native. On these targets we use the original
device table for FFS, even though we previously thought that it would
never apply to any target other than dsample, leonardo and gtamodem.
We have previously added Samsung K5L33xxCAM (a new kind of multi-ID device)
to the generic table to support its use in Huawei GTM900-B modules; now
we got news that some slightly older GTM900-B specimen used S71PL032J
instead, so we are now adding PL032J as well.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 30 Jan 2020 17:45:48 +0000 |
parents | 945cf7f506b2 |
children |
line wrap: on
line source
/****************************************************************************** * Flash File System (ffs) * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com * * ffs test scaffold/framework * * $Id: tffs.c 1.12.1.1.1.20 Fri, 19 Dec 2003 12:00:13 +0100 tsj $ * ******************************************************************************/ #ifndef TARGET #include "ffs.cfg" #endif #include "ffs/ffs.h" #include "ffs/board/core.h" #include "ffs/board/tffs.h" #include "ffs/board/tdata.h" #include "ffs/board/tmffs.h" #include "ffs/board/ffstrace.h" #if (TARGET == 1) #include "ffs/board/task.h" #endif #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> /****************************************************************************** * Prototypes and Globals ******************************************************************************/ struct dir_s dir; struct stat_s stat; struct xstat_s xstat; int error; #if (TARGET == 1) int smallbuf_size = 512; int bigbuf_size = 65536; #else int smallbuf_size = 1024; int bigbuf_size = 1024*1024*8; #endif char *smallbuf = 0; char *bigbuf = 0; /****************************************************************************** * Globals and Main ******************************************************************************/ extern struct testcase_s testcase[]; struct test_s { char *name; // name of currently executing test case int numcases; // number of test cases run so far int numcalls; // total number of ffs function calls so far int numfails; // total number of failed test cases int keepgoing; // keep going when a test case fails } test; struct ffs_params_s param; /****************************************************************************** * Main Functions ******************************************************************************/ effs_t ffs_initialize(void); effs_t ffs_exit(void); // Each test case returns zero on success, non-zero on failure. // test_execute() decides whether to continue with remaining test cases or // not. #if (TARGET == 0) void test_listall(void) { struct testcase_s *p; printf("Test Cases:\n"); for (p = testcase; p->name != 0; p++) { printf("%8s: %s\n", p->name, p->comment); } } #endif // <tests> is a comma-separated string of names of the test cases to // run. Return number of test cases that failed. This is typically only 1, // unless arg_keepgoing is set in which case it can be several. int test_run(char *tests) { struct testcase_s *ptc; int i, failed, tparams[FFS_TESTCASE_PARAMS_MAX]; struct this_test_s this; char *pname, *testsnew; failed = 0; while (*tests != 0 && (failed == 0 || test.keepgoing)) { // Make local copy of test case name. We have to make local copies // because we can be recursively called pname = this.name; while (isalpha(*tests) && *tests != 0 && *tests != ';') *pname++ = *tests++; *pname = 0; // Reset test case parameter(s) for (i = 0; i < FFS_TESTCASE_PARAMS_MAX; i++) tparams[i] = 0; // Collect parameter(s) for test case i = 0; while (isdigit(*tests)) { tparams[i] = strtol(tests, &testsnew, 0); if (tests == testsnew) break; tests = testsnew; if (*tests == ',') tests++; i++; if (i > FFS_TESTCASE_PARAMS_MAX) { ttw(ttr(TTrTest, "TEST %s has TOO MANY PARAMS" NL, this.name)); tw(tr(TR_FUNC, TrTest, "TEST %s TOO MANY PARAMS\n", this.name)); return 1; } } if (*tests == ';') tests++; // Lookup the test name in the array of test cases for (ptc = testcase; ptc->name != 0; ptc++) { if (strcmp(this.name, ptc->name) == 0) break; } if (ptc->name == 0) { ttw(ttr(TTrTest, "TEST %s UNKNOWN" NL, this.name)); tw(tr(TR_FUNC, TrTest, "TEST %s UNKNOWN\n", this.name)); return 1; } this.numcalls = test.numcalls; test_begin(this.name, tparams); i = ptc->function(tparams[0], tparams[1]); if (i != 0) { failed++; test_error(&this, test.numcalls); } test_end(&this, test.numcalls); } return failed; } // Overall test initialization. Read static ffs params with ffs_query() void test_init(int keepgoing) { test.numcases = 0; test.numcalls = 0; test.numfails = 0; test.keepgoing = keepgoing; memset(¶m, 0, sizeof(struct ffs_params_s)); if (smallbuf == 0) { #if (TARGET == 1) smallbuf = (char*)target_malloc(smallbuf_size); #else smallbuf = malloc(smallbuf_size); #endif tw(tr(TR_FUNC, TrTest, "smallbuf = 0x%X, %d\n", smallbuf, smallbuf_size)); } if (bigbuf == 0) { #if (TARGET == 1) // We continuously halve the buffer size until we succeed to allocate // it. while(1) { if ((bigbuf = (char*)target_malloc(bigbuf_size)) != 0) break; bigbuf_size /= 2; } #else bigbuf = malloc(bigbuf_size); #endif tw(tr(TR_FUNC, TrTest, "bigbuf = 0x%X, %d\n", bigbuf, bigbuf_size)); } test_tdata_init(); tffs_initialize(); } void test_exit(void) { test_state_print(0); } // Begin new test case void test_begin(char *name, int *params) { test.numcases++; tw(tr(TR_BEGIN, TrTest, "TEST %s(%d,%d)\n", name, params[0], params[1])); ttw(ttr(TTrTest, "TEST %s(%d,%d)" NL, name, params[0], params[1])); } void test_end(struct this_test_s *test, int n) { int objects = 0; ffs_query(Q_TOTAL_OBJECTS, (uint16 *) &objects); tw(tr(TR_FUNC, TrTestHigh, "(total objects = %d)\n", objects)); tw(tr(TR_END, TrTest, "")); //tw(tr(TR_END, TrTest, "TEST END %s (calls = %d)\n", // test->name, n - test->numcalls)); } void test_error(struct this_test_s *test, int n) { ttw(ttr(TTrTest, "TEST FAIL %s, call %d" NL, test->name, n - test->numcalls)); tw(tr(TR_FUNC, TrTest, "TEST FAIL %s, call %d\n", test->name, n - test->numcalls)); } /****************************************************************************** * Miscellaneous ******************************************************************************/ int test_ffs_state_get(struct ffs_state_s *s) { memset(s, 0, sizeof(struct ffs_state_s)); error = ffs_query(Q_INODES_USED, (uint16 *) &s->inodes_used); error += ffs_query(Q_INODES_LOST, (uint16 *) &s->inodes_lost); error += ffs_query(Q_OBJECTS_FREE, (uint16 *) &s->objects_free); error += ffs_query(Q_TOTAL_OBJECTS, (uint16 *) &s->objects_total); error += ffs_query(Q_BYTES_USED, (uint16 *) &s->bytes_used); error += ffs_query(Q_BYTES_LOST, (uint16 *) &s->bytes_lost); error += ffs_query(Q_BYTES_FREE, (uint16 *) &s->bytes_free); error += ffs_query(Q_BLOCKS_FREE, (uint16 *) &s->blocks_free); return error; } void test_ffs_state_copy(struct ffs_state_s *dst, struct ffs_state_s *src) { memcpy(dst, src, sizeof(struct ffs_state_s)); } void test_state_print(struct ffs_state_s *state) { struct ffs_state_s mystate; if (state == 0) { state = &mystate; test_ffs_state_get(state); } tw(tr(TR_FUNC, TrTest, "\nFFS State Summary:\n\n")); ttw(str(TTrTest, NL "FFS State Summary:" NL NL)); tw(tr(TR_FUNC, TrTest, " block_size = %d\n", param.block_size)); tw(tr(TR_FUNC, TrTest, " bytes_avail = %d\n\n", param.bytes_avail)); ttw(ttr(TTrTest, " block_size = %d" NL, param.block_size)); ttw(ttr(TTrTest, " bytes_avail = %d" NL NL, param.bytes_avail)); test_state_bytes_print(state, 0); test_state_objects_print(state, 0); } void test_state_objects_print(struct ffs_state_s *old, struct ffs_state_s *new) { ttw(str(TTrTest, " inodes objects" NL)); ttw(str(TTrTest, " -------------------------------------------" NL)); ttw(str(TTrTest, " objects: used lost free total" NL)); ttw(ttr(TTrTest, " old: %6d %6d %6d %6d" NL, old->inodes_used, old->inodes_lost, old->objects_free, old->objects_total)); tw(tr(TR_FUNC, TrTest, " inodes objects\n")); tw(tr(TR_FUNC, TrTest, " -------------------------------------------\n")); tw(tr(TR_FUNC, TrTest, " objects: used lost free total\n")); tw(tr(TR_FUNC, TrTest, " old: %6d %6d %6d %6d\n", old->inodes_used, old->inodes_lost, old->objects_free, old->objects_total)); if (new != NULL) { ttw(ttr(TTrTest, " new: %6d %6d %6d %6d" NL, new->inodes_used, new->inodes_lost, new->objects_free, new->objects_total)); ttw(ttr(TTrTest, " diff: %6d %6d %6d %6d" NL, new->inodes_used - old->inodes_used, new->inodes_lost - old->inodes_lost, new->objects_free - old->objects_free, new->objects_total - old->objects_total)); tw(tr(TR_FUNC, TrTest, " new: %6d %6d %6d %6d\n", new->inodes_used, new->inodes_lost, new->objects_free, new->objects_total)); tw(tr(TR_FUNC, TrTest, " diff: %6d %6d %6d %6d\n", new->inodes_used - old->inodes_used, new->inodes_lost - old->inodes_lost, new->objects_free - old->objects_free, new->objects_total - old->objects_total)); } ttw(str(TTrTest, "" NL)); tw(tr(TR_FUNC, TrTest, "\n")); } void test_state_bytes_print(struct ffs_state_s *old, struct ffs_state_s *new) { tw(tr(TR_FUNC, TrTest, " bytes: used lost free total\n")); tw(tr(TR_FUNC, TrTest, " old: %8d %8d %8d %8d\n", old->bytes_used, old->bytes_lost, old->bytes_free, param.bytes_max)); tw(tr(TR_FUNC, TrTest, " +/-: %8d %8d\n", old->bytes_used - old->bytes_lost, old->bytes_free + old->bytes_lost)); ttw(str(TTrTest, " bytes: used lost free total" NL)); ttw(ttr(TTrTest, " old: %8d %8d %8d %8d" NL, old->bytes_used, old->bytes_lost, old->bytes_free, param.bytes_max)); ttw(ttr(TTrTest, " +/-: %8d %8d" NL, old->bytes_used - old->bytes_lost, old->bytes_free + old->bytes_lost)); if (new != NULL) { tw(tr(TR_FUNC, TrTest, " new: %8d %8d %8d\n", new->bytes_used, new->bytes_lost, new->bytes_free)); tw(tr(TR_FUNC, TrTest, " diff: %8d %8d %8d\n", new->bytes_used - old->bytes_used, new->bytes_lost - old->bytes_lost, new->bytes_free - old->bytes_free)); ttw(ttr(TTrTest, " new: %8d %8d %8d" NL, new->bytes_used, new->bytes_lost, new->bytes_free)); ttw(ttr(TTrTest, " diff: %8d %8d %8d" NL, new->bytes_used - old->bytes_used, new->bytes_lost - old->bytes_lost, new->bytes_free - old->bytes_free)); } tw(tr(TR_FUNC, TrTest, "\n")); ttw(str(TTrTest, "" NL)); } // Retrieve all static ffs parameters with ffs_query() int test_ffs_params_get(void) { error = ffs_query(Q_FILENAME_MAX, ¶m.filename_max); error += ffs_query(Q_PATH_DEPTH_MAX, ¶m.pathdepth_max); error += ffs_query(Q_INODES_MAX, ¶m.inodes_max); error += ffs_query(Q_BYTES_MAX, ¶m.bytes_max); error += ffs_query(Q_DEV_BLOCKS, ¶m.numblocks); error += ffs_query(Q_DEV_ATOMSIZE, ¶m.atomsize); error += ffs_query(Q_BLOCKS_FREE_MIN, ¶m.blocks_free_min); // Compute block size param.block_size = param.bytes_max / param.numblocks; // Compute total number of available storage space, subtracting // fs.blocks_free_min plus one block for inodes param.bytes_avail = param.bytes_max - (param.block_size * (1 + param.blocks_free_min)); // Compute number of blocks available for data storage param.data_blocks = param.numblocks - (1 + param.blocks_free_min); return error; } void test_statistics_print(void) { tw(tr(TR_FUNC, TrTest, "Data allocated(%dMB)\n", stats.data_allocated>>20)); tw(tr(TR_FUNC, TrTest, "Reclaim candidates: most-lost(%d), most-unused(%d), youngest(%d)\n", stats.drec.most_lost, stats.drec.most_unused, stats.drec.youngest)); tw(tr(TR_FUNC, TrTest, "Data reclaimed: lost(%dMB), valid(%dMB)\n", stats.drec.lost[0]>>20 , stats.drec.valid[0]>>20)); tw(tr(TR_FUNC, TrTest, "Inodes reclaimed: num(%d), valid(%d), lost(%d)\n", stats.irec.num, stats.irec.valid, stats.irec.lost)); ttw(ttr(TTrTest, "Data allocated(%dMB)\n" NL, stats.data_allocated>>20)); ttw(ttr(TTrTest, "Reclaim candidates: most-lost(%d), most-unused(%d), youngest(%d)\n" NL, stats.drec.most_lost, stats.drec.most_unused, stats.drec.youngest)); ttw(ttr(TTrTest, "Data reclaimed: lost(%dMB), valid(%dMB)\n" NL, stats.drec.lost[0]>>20 , stats.drec.valid[0]>>20)); ttw(ttr(TTrTest, "Inodes reclaimed: num(%d), valid(%d), lost(%d)\n" NL, stats.irec.num, stats.irec.valid, stats.irec.lost)); } /****************************************************************************** * Test and Expect Functions ******************************************************************************/ int test_expect(int n, int xn) { if (n == xn) return 0; tw(tr(TR_FUNC, TrTest, "ERROR: expect(%d,%d): got %d, '%s', expected %d, '%s'\n", n, xn, n, ffs_strerror(n), xn, ffs_strerror(xn))); ttw(ttr(TTrTest, "ERROR: expect(%d,%d)" NL, n, xn)); return -1; } // Expect a return code >= 0 meaning EFFS_OK. int test_expect_ok(int n) { if (n >= 0) return 0; tw(tr(TR_FUNC, TrTest, "ERROR: expect_ok(%d) got %d, '%s', expected >= EFFS_OK\n", n, ffs_strerror(n))); ttw(ttr(TTrTest, "ERROR: expect_ok(%d)" NL, n)); return -1; } int test_expect_equal(int n, int xn) { if (n == xn) return 0; tw(tr(TR_FUNC, TrTest, "ERROR: got %d, expected %d\n", n, xn)); ttw(ttr(TTrTest, "ERROR: expect_eq(%d,%d" NL, n, xn)); return -1; } int test_expect_not_equal(int n, int xn) { if (n != xn) return 0; tw(tr(TR_FUNC, TrTest, "ERROR: expect_ne(%d)\n", n)); ttw(ttr(TTrTest, "ERROR: expect_ne(%d)" NL, n)); return -1; } int test_expect_greater_than(int n, int xn) { if (n > xn) return 0; tw(tr(TR_FUNC, TrTest, "ERROR: expect_gt(%d,%d) got %d but expected > %d\n", n, xn, n, xn)); ttw(ttr(TTrTest, "ERROR: expect_gt(%d,%d)" NL, n, xn)); return -1; } int test_expect_data(const void *data1, const void *data2, int size) { if (memcmp(data1, data2, size) == 0) return 0; tw(tr(TR_FUNC, TrTest, "ERROR: expect_data(%d) got unexpected data\n", size)); ttw(ttr(TTrTest, "ERROR: expect_data(%d)" NL, size)); return -1; } // Check that contents of file with name <name> is the same as <data> of // size <size>. int test_expect_file(const char *name, const void *data, int size) { test.numcalls++; if (size > bigbuf_size) { tw(tr(TR_FUNC, TrTest, "WARNING: expect_file(%d) buffer too small\n", size)); ttw(ttr(TTrTest, "WARNING: expect_file(%d) buffer too small" NL, size)); #if (TARGET == 1) return 0; #endif return -1; } error = ffs_file_read(name, bigbuf, size); if (test_expect_greater_than(error, EFFS_OK - 1)) return -1; return test_expect_data(bigbuf, data, size); } int test_expect_state(struct ffs_state_s *old, struct ffs_state_s *new) { int old_total, new_total; old_total = old->inodes_used - old->inodes_lost; new_total = new->inodes_used - new->inodes_lost; if (old->objects_total == new->objects_total && old->objects_total == new_total && new->objects_total == old_total && old->bytes_used == new->bytes_used && old->bytes_lost == new->bytes_lost && old->bytes_free == new->bytes_free) { return 0; } ttw(str(TTrTest, "ERROR: ffs state mismatch:" NL NL)); tw(tr(TR_FUNC, TrTest, "ERROR: ffs state mismatch:\n\n")); test_state_objects_print(old, new); test_state_bytes_print(old, new); return -1; } // Check if number of objects is unchanged int test_expect_objects(struct ffs_state_s *old, struct ffs_state_s *new) { int old_total, new_total; test_ffs_state_get(new); old_total = old->inodes_used - old->inodes_lost; new_total = new->inodes_used - new->inodes_lost; if (old->objects_total == new->objects_total && old->objects_total == new_total && new->objects_total == old_total) { return 0; } ttw(ttr(TTrTest, "ERROR: expect_objects(%d, %d, %d, %d, %d, %d)" NL)); tw(tr(TR_FUNC, TrTest, "ERROR: ffs state mismatch:\n\n")); test_state_objects_print(old, new); return -1; } /****************************************************************************** * FFS Functions ******************************************************************************/ effs_t tffs_fcreate(const char *name, void *addr, int size) { test.numcalls++; return ffs_fcreate(name, addr, size); } effs_t tffs_fupdate(const char *name, void *addr, int size) { test.numcalls++; return ffs_fupdate(name, addr, size); } effs_t tffs_fwrite(const char *name, void *addr, int size) { test.numcalls++; return ffs_fwrite(name, addr, size); } effs_t tffs_file_write(const char *name, void *addr, int size, uint16 option) { test.numcalls++; return ffs_file_write(name, addr, size, option); } effs_t tffs_mkdir(const char *name) { test.numcalls++; return ffs_mkdir(name); } effs_t tffs_symlink(const char *name, const char *actualpath) { test.numcalls++; return ffs_symlink(name, actualpath); } effs_t tffs_remove(const char *name) { test.numcalls++; return ffs_remove(name); } effs_t tffs_fcontrol(const char *name, int8 action, uint16 param) { test.numcalls++; return ffs_fcontrol(name, action, param); } effs_t tffs_preformat(uint16 magic) { test.numcalls++; return ffs_preformat(magic); } effs_t tffs_format(const char *name, uint16 magic) { test.numcalls++; return ffs_format(name, magic); } int tffs_fread(const char *name, void *addr, int size) { test.numcalls++; return ffs_file_read(name, addr, size); } int tffs_file_read(const char *name, void *addr, int size) { test.numcalls++; return ffs_file_read(name, addr, size); } int tffs_opendir(const char *name, struct dir_s *dir) { test.numcalls++; return ffs_opendir(name, dir); } int tffs_readdir (struct dir_s *dir, char *name, int8 size) { test.numcalls++; return ffs_readdir(dir, name, size); } int tffs_readlink(const char *name, char *addr, int size) { test.numcalls++; return ffs_readlink(name, addr, size); } int tffs_rename(const char *oldname, const char *newname) { test.numcalls++; return ffs_rename(oldname, newname); } effs_t tffs_stat(const char *name, struct stat_s *stat) { test.numcalls++; return ffs_stat(name, stat); } effs_t tffs_fstat(fd_t fdi, struct stat_s *stat) { test.numcalls++; return ffs_fstat(fdi, stat); } effs_t tffs_linkstat(const char *name, struct stat_s *stat) { test.numcalls++; return ffs_lstat(name, stat); } effs_t tffs_lstat(const char *name, struct stat_s *stat) { test.numcalls++; return ffs_lstat(name, stat); } effs_t tffs_xlstat(const char *name, struct xstat_s *stat) { test.numcalls++; return ffs_xlstat(name, stat); } effs_t tffs_query(int8 query, void *p) { return ffs_query(query, p); } effs_t tffs_initialize(void) { effs_t myerror; struct ffs_stats_s old_stats; test.numcalls++; memcpy(&old_stats, &stats, sizeof(struct ffs_stats_s)); myerror = ffs_initialize(); memcpy(&stats, &old_stats, sizeof(struct ffs_stats_s)); test_ffs_params_get(); return myerror; } effs_t tffs_exit(void) { test.numcalls++; return ffs_exit(); } fd_t tffs_open(const char *pathname, ffs_options_t options) { test.numcalls++; return ffs_open(pathname, options); } effs_t tffs_close(fd_t fdi) { test.numcalls++; return ffs_close(fdi); } int tffs_write(fd_t fdi, void *addr, int size) { test.numcalls++; return ffs_write(fdi, addr, size); } int tffs_read(fd_t fdi, void *addr, int size) { test.numcalls++; return ffs_read(fdi, addr, size); } int tffs_seek(fd_t fdi, int offset, int whence) { test.numcalls++; return ffs_seek(fdi, offset, whence); } effs_t tffs_truncate(const char *path, offset_t length) { test.numcalls++; return ffs_truncate(path, length); } effs_t tffs_ftruncate(fd_t fdi, offset_t length) { test.numcalls++; return ffs_ftruncate(fdi, length); } effs_t tffs_fdatasync(fd_t fdi) { test.numcalls++; return ffs_fdatasync(fdi); }