# HG changeset patch # User Michael Spacefalcon # Date 1389513540 0 # Node ID 2900fe603f8ab3e891644985fd6045607f68d87d # Parent 0848c7f419fd2c296e0b89048a0b8701248e1f7d beginning of MPFFS->TIFFS naming convention change diff -r 0848c7f419fd -r 2900fe603f8a doc/TIFFS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/TIFFS Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,50 @@ +All TI GSM firmwares known to this author (FreeCalypso developer Space Falcon) +implement some kind of flash file system, or FFS. Several different FFS code +implementations, and correspondingly several different on-flash data formats, +have been used throughout the history of TI's involvement in the wireless +terminal business. The FFS incarnation of primary interest to the FreeCalypso +project is the one invented by Mads Meisner-Jensen at TI in the early 2000s +(at least according to the comments in the sources available to us), and it is +relevant to us in the following ways: + +* When targeting the GSM modem in Openmoko's GTA01/02 smartphones, we need to + work with the original FFS from the factory (call it MokoFFS), the same FFS + as used by the mokoN firmwares: this FFS contains the IMEI and the RF + calibration values from the factory, which we most certainly don't want to go + without. + +* The Leonardo firmware semi-src which we are using as the reference for + building our own full source, multi-target GSM fw contains a turnkey-working + implementation of this very FFS, using the on-flash format in question and + providing run-time APIs expected by the rest of the GSM fw suite. Following + the principle of ``if it ain't broke, don't fix it'', we can use this FFS not + only on the gtamodem target, but also on other targets, including those where + we would be starting from a blank state and thus have the freedom to use + whatever FFS we like. + +* The original proprietary fw on the Pirelli DP-L10 phone also happens to use + an FFS in the same format. Pirelli's FFS does *not* contain the IMEI or any + of the RF calibration values though, and trying to reuse it directly for our + own FC GSM fw seems to be more trouble than benefit - so we'll probably have + our fw start with a blank TIFFS instead - but there is still insight to be + gained from in-vitro examination of captured Pirelli FFS images. + +Naming +====== + +I have previously referred to the FFS format in question as Mokopir-FFS or +MPFFS, from "Moko" and "Pirelli". I was originally hesitant to call it TIFFS, +as lacking the source code, I had no way of knowing whether the FFS format and +implementation were of TI's own invention, or something that TI licensed as a +black box from one of their many proprietary software partners. (I was unable +to identify it as any well-known, industry-standard FFS format, but absence of +evidence is not evidence of absence.) But now that we have TI's original source +code which implements this FFS (first the MV100-0.1.rar source, then the full +Leonardo one), complete with comments and a HISTORY file, we know that our FFS +was invented and implemented by someone named Mads Meisner-Jensen at TI - I'm +guessing in the SSA group in Nice, France. + +I am now making a naming transition from MPFFS to TIFFS: there is really no +link between this FFS format and the Openmoko+Pirelli duo, other than the +happenstance of me having first encountered this FFS on these two GSM device +brands, and the name TIFFS is more neutrally-descriptive. diff -r 0848c7f419fd -r 2900fe603f8a ffstools/tiffs-rd/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-rd/README Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,33 @@ +The utility being developed in this source directory will allow one to examine +("in vitro") flash file system (FFS) images read out of TI GSM devices - or +more precisely, out of GSM devices using a TI chipset and running TI's GSM +firmware versions from the late Calypso era. The FFS version in question is +implemented in our own FreeCalypso GSM fw, also happens to be used by the +original proprietary firmware on the Pirelli DP-L10, and on some devices like +Openmoko GTA0x the use of this FFS format is required in order to make use of +the factory IMEI and RF calibration data. + +This new tiffs utility is intended to replace the earlier mpffs-* utilities +released in the summer of SE52 (A.D. 2013), and will also incorporate the +additional examination functionality that was developed as part of the +"pirollback" utilities. + +Naming +====== + +I have previously referred to the FFS format in question as Mokopir-FFS or +MPFFS, from "Moko" and "Pirelli". I was originally hesitant to call it TIFFS, +as lacking the source code, I had no way of knowing whether the FFS format and +implementation were of TI's own invention, or something that TI licensed as a +black box from one of their many proprietary software partners. (I was unable +to identify it as any well-known, industry-standard FFS format, but absence of +evidence is not evidence of absence.) But now that we have TI's original source +code which implements this FFS (first the MV100-0.1.rar source, then the full +Leonardo one), complete with comments and a HISTORY file, we know that our FFS +was invented and implemented by someone named Mads Meisner-Jensen at TI - I'm +guessing in the SSA group in Nice, France. + +I am now making a naming transition from MPFFS to TIFFS: there is really no +link between this FFS format and the Openmoko+Pirelli duo, other than the +happenstance of me having first encountered this FFS on these two GSM device +brands, and the name TIFFS is more neutrally-descriptive. diff -r 0848c7f419fd -r 2900fe603f8a ffstools/tiffs-rd/pathname.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-rd/pathname.h Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,3 @@ +#define MAX_FN_COMPONENT 20 +#define MAX_DIR_NEST 6 +#define PATHNAME_BUF_SIZE ((MAX_FN_COMPONENT+1) * MAX_DIR_NEST + 2) diff -r 0848c7f419fd -r 2900fe603f8a ffstools/tiffs-rd/struct.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-rd/struct.h Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,40 @@ +/* actual TIFFS on-media structure */ +struct inode_flash { + u16 len; + u8 reserved1; + u8 type; + u16 descend; + u16 sibling; + u32 dataptr; + u16 sequence; + u16 updates; +}; + +struct journal_entry { + u8 status; + u8 objtype; + u16 this_ino; + u16 link_ptr; + u16 replacee; + u32 location; + u16 size; + u16 repli; /* ??? */ +}; + +/* our own struct for convenience */ +struct inode_info { + struct inode_flash *flash; + int parent; + int type; + u8 *dataptr; + u32 offset; + u32 rawloc; + u16 len; + int descend; + int sibling; + u8 *byte_after_name; + /* info added from parsing the journal */ + struct journal_entry *jflash; + int j_unlink_ptr; + int j_oldver; +}; diff -r 0848c7f419fd -r 2900fe603f8a ffstools/tiffs-rd/types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-rd/types.h Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,12 @@ +/* + * I like using u8/u16/u32, but they don't seem to be defined anywhere. + * So I solve the whole portability problem by defining them myself. + */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; diff -r 0848c7f419fd -r 2900fe603f8a target-utils/Makefile --- a/target-utils/Makefile Tue Jan 07 05:58:11 2014 +0000 +++ b/target-utils/Makefile Sun Jan 12 07:59:00 2014 +0000 @@ -1,5 +1,5 @@ PROGS= helloapp loadagent pirexplore -LIBS= libcommon libload libmpffs libprintf +LIBS= libcommon libload libprintf libtiffs SUBDIR= ${PROGS} ${LIBS} default: loadagent @@ -7,7 +7,7 @@ helloapp: libcommon libprintf loadagent: libcommon libload libprintf -pirexplore: libcommon libload libmpffs libprintf +pirexplore: libcommon libload libprintf libtiffs ${SUBDIR}: FRC cd $@; ${MAKE} ${MFLAGS} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/Makefile --- a/target-utils/libmpffs/Makefile Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -CC= arm-elf-gcc -CFLAGS= -Os -fno-builtin -CPPFLAGS=-I../include -AR= arm-elf-ar -RANLIB= arm-elf-ranlib - -OBJS= basicfind.o cmd_find.o findfile.o globals.o init.o rdinmem.o - -all: libmpffs.a - -libmpffs.a: ${OBJS} - ${AR} cru $@ ${OBJS} - ${RANLIB} $@ - -clean: - rm -f *.[oa] *errs diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/basicfind.c --- a/target-utils/libmpffs/basicfind.c Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -#include -#include "types.h" -#include "struct.h" -#include "globals.h" -#include "macros.h" - -extern char *index(); - -static -find_named_child(start, seekname) - char *seekname; -{ - int ino; - struct inode *irec; - - for (ino = start; ino != 0xFFFF; ino = irec->sibling) { - irec = mpffs_active_index + ino; - if (!irec->type) - continue; - if (!strcmp(inode_to_dataptr(irec), seekname)) - return(ino); - } - return(0); -} - -mpffs_pathname_to_inode(pathname) - char *pathname; -{ - int ino, stat; - struct inode *irec; - char *cur, *next; - - stat = mpffs_init(); - if (stat < 0) - return(stat); - cur = pathname; - if (*cur == '/') - cur++; - for (ino = mpffs_root_ino; cur; cur = next) { - if (!*cur) - break; - next = index(cur, '/'); - if (next == cur) { - printf("malformed pathname: multiple adjacent slashes\n"); - return(-1); - } - if (next) - *next++ = '\0'; - irec = mpffs_active_index + ino; - if (irec->type != OBJTYPE_DIR) { - printf("Error: non-terminal non-directory\n"); - if (next) - next[-1] = '/'; - return(-1); - } - ino = find_named_child(irec->descend, cur); - if (next) - next[-1] = '/'; - if (!ino) { - printf("Error: pathname component not found\n"); - return(-1); - } - } - return(ino); -} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/cmd_find.c --- a/target-utils/libmpffs/cmd_find.c Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -#include -#include "types.h" - -void -cmd_find(argbulk) - char *argbulk; -{ - char *argv[2]; - int stat, cont; - u8 *start; - size_t size; - - if (parse_args(argbulk, 1, 1, argv, 0) < 0) - return; - stat = mpffs_find_file(argv[0], &start, &size, &cont); - if (stat < 0) - return; - printf("chunk @%08X size %x\n", (u32)start, (u32)size); - while (cont) { - stat = mpffs_get_segment(cont, &start, &size, &cont); - if (stat < 0) - return; - printf("chunk @%08X size %x\n", (u32)start, (u32)size); - } -} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/findfile.c --- a/target-utils/libmpffs/findfile.c Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -#include -#include "types.h" -#include "struct.h" -#include "globals.h" -#include "macros.h" - -static u8 * -find_endofchunk(ino) -{ - struct inode *irec = mpffs_active_index + ino; - u8 *p; - int i; - - p = inode_to_dataptr(irec) + irec->len; - for (i = 0; i < 16; i++) { - p--; - if (!*p) - return(p); - if (*p != 0xFF) - break; - } - printf("Error: inode #%x has no valid termination\n", ino); - return(p); /* XXX */ -} - -mpffs_find_file(pathname, startret, sizeret, continue_ret) - char *pathname; - u8 **startret; - size_t *sizeret; - int *continue_ret; -{ - int ino, cont; - struct inode *irec; - u8 *start, *end; - int size; - - ino = mpffs_pathname_to_inode(pathname); - if (ino <= 0) - return(-1); - irec = mpffs_active_index + ino; - if (irec->type != OBJTYPE_FILE) { - printf("Error: %s is not a regular file\n", pathname); - return(-1); - } - start = inode_to_dataptr(irec); - start += strlen(start) + 1; - end = find_endofchunk(ino); - size = end - start; - if (size < 0) - size = 0; - cont = irec->descend; - if (cont == 0xFFFF) - cont = 0; - if (startret) - *startret = start; - if (sizeret) - *sizeret = size; - if (continue_ret) - *continue_ret = cont; - return(0); -} - -mpffs_get_segment(ino, startret, sizeret, continue_ret) - int ino; - u8 **startret; - size_t *sizeret; - int *continue_ret; -{ - int cont; - struct inode *irec; - u8 *start, *end; - int size; - - for (;;) { - irec = mpffs_active_index + ino; - if (irec->type) - break; - if (irec->sibling == 0xFFFF) { - printf("Error: segment inode #%d: deleted and no sibling\n", - ino); - return(-1); - } - ino = irec->sibling; - } - if (irec->type != OBJTYPE_SEGMENT) { - printf("Error: inode #%x is not a segment\n", ino); - return(-1); - } - start = inode_to_dataptr(irec); - end = find_endofchunk(ino); - size = end - start; - if (size <= 0) { - printf("Error: segment inode #%x: bad length\n", ino); - return(-1); - } - cont = irec->descend; - if (cont == 0xFFFF) - cont = 0; - if (startret) - *startret = start; - if (sizeret) - *sizeret = size; - if (continue_ret) - *continue_ret = cont; - return(0); -} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/globals.c --- a/target-utils/libmpffs/globals.c Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -/* global variables for the MPFFS reader code */ - -#include "types.h" -#include "struct.h" - -struct inode *mpffs_active_index; -int mpffs_root_ino; -int mpffs_init_done; diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/globals.h --- a/target-utils/libmpffs/globals.h Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -/* global variables for the MPFFS reader code - extern declarations */ - -extern struct inode *mpffs_active_index; -extern int mpffs_root_ino; -extern int mpffs_init_done; - -extern const u32 mpffs_base_addr; -extern const u32 mpffs_sector_size; -extern const int mpffs_nsectors; diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/init.c --- a/target-utils/libmpffs/init.c Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -#include "types.h" -#include "struct.h" -#include "globals.h" -#include "macros.h" - -static const u8 ffs_sector_signature[6] = {'F', 'f', 's', '#', 0x10, 0x02}; -static const u8 blank_flash_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF}; - -static -find_indexblk() -{ - u32 sector_addr; - u8 *sector_ptr; - int i; - - printf("Looking for MPFFS active index block\n"); - sector_addr = mpffs_base_addr; - for (i = 0; i < mpffs_nsectors; i++) { - sector_ptr = (u8 *) sector_addr; - if (!bcmp(sector_ptr, ffs_sector_signature, 6) && - sector_ptr[8] == 0xAB) { - printf("Found at %08X\n", sector_addr); - mpffs_active_index = (struct inode *) sector_ptr; - return(0); - } - sector_addr += mpffs_sector_size; - } - printf("Error: Not found in any of the %d candidate sectors\n", - mpffs_nsectors); - return(-1); -} - -static -find_rootino() -{ - int ino; - struct inode *irec; - - printf("Looking for the root inode\n"); - for (ino = 1; ; ino++) { - if (ino >= mpffs_sector_size >> 4) { - printf("Error: Hit end of sector, no root inode found\n"); - return(-1); - } - irec = mpffs_active_index + ino; - if (!bcmp((u8 *) irec, blank_flash_line, 16)) { - printf("Error: Hit blank flash, no root inode found\n"); - return(-1); - } - if (irec->type == OBJTYPE_DIR && *inode_to_dataptr(irec) == '/') - break; - } - printf("Found at inode #%x\n", ino); - mpffs_root_ino = ino; - return(0); -} - -mpffs_init() -{ - int stat; - - if (mpffs_init_done) - return(0); - stat = find_indexblk(); - if (stat < 0) - return(stat); - stat = find_rootino(); - if (stat < 0) - return(stat); - mpffs_init_done = 1; - return(0); -} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/macros.h --- a/target-utils/libmpffs/macros.h Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -#define inode_to_dataptr(i) ((u8 *)mpffs_base_addr + ((i)->dataptr << 4)) diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/rdinmem.c --- a/target-utils/libmpffs/rdinmem.c Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -#include -#include "types.h" -#include "struct.h" -#include "globals.h" -#include "macros.h" - -mpffs_read_into_ram(pathname, buf, maxlen, lenrtn) - char *pathname; - u8 *buf; - size_t maxlen, *lenrtn; -{ - int stat, cont; - u8 *chunk_start; - size_t chunk_size, real_len, roomleft; - - stat = mpffs_find_file(pathname, &chunk_start, &chunk_size, &cont); - if (stat < 0) - return(stat); - if (chunk_size > maxlen) { -toobig: printf("Error: %s is bigger than the read buffer\n", pathname); - return(-1); - } - real_len = chunk_size; - bcopy(chunk_start, buf, chunk_size); - buf += chunk_size; - roomleft = maxlen - chunk_size; - while (cont) { - stat = mpffs_get_segment(cont, &chunk_start, &chunk_size, - &cont); - if (stat < 0) - return(stat); - if (chunk_size > roomleft) - goto toobig; - real_len += chunk_size; - bcopy(chunk_start, buf, chunk_size); - buf += chunk_size; - roomleft -= chunk_size; - } - if (lenrtn) - *lenrtn = real_len; - return(0); -} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libmpffs/struct.h --- a/target-utils/libmpffs/struct.h Tue Jan 07 05:58:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -struct inode { - u16 len; - u8 reserved1; - u8 type; - u16 descend; - u16 sibling; - u32 dataptr; - u16 sequence; - u16 updates; -}; - -#define OBJTYPE_FILE 0xF1 -#define OBJTYPE_DIR 0xF2 -#define OBJTYPE_SEGMENT 0xF4 - -struct journal { - u8 status; - u8 objtype; - u16 this_ino; - u16 link_ptr; - u16 replacee; - u32 location; - u16 size; - u16 repli; /* ??? */ -}; diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/Makefile Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,16 @@ +CC= arm-elf-gcc +CFLAGS= -Os -fno-builtin +CPPFLAGS=-I../include +AR= arm-elf-ar +RANLIB= arm-elf-ranlib + +OBJS= basicfind.o cmd_find.o findfile.o globals.o init.o rdinmem.o + +all: libtiffs.a + +libtiffs.a: ${OBJS} + ${AR} cru $@ ${OBJS} + ${RANLIB} $@ + +clean: + rm -f *.[oa] *errs diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/basicfind.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/basicfind.c Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,65 @@ +#include +#include "types.h" +#include "struct.h" +#include "globals.h" +#include "macros.h" + +extern char *index(); + +static +find_named_child(start, seekname) + char *seekname; +{ + int ino; + struct inode *irec; + + for (ino = start; ino != 0xFFFF; ino = irec->sibling) { + irec = mpffs_active_index + ino; + if (!irec->type) + continue; + if (!strcmp(inode_to_dataptr(irec), seekname)) + return(ino); + } + return(0); +} + +mpffs_pathname_to_inode(pathname) + char *pathname; +{ + int ino, stat; + struct inode *irec; + char *cur, *next; + + stat = mpffs_init(); + if (stat < 0) + return(stat); + cur = pathname; + if (*cur == '/') + cur++; + for (ino = mpffs_root_ino; cur; cur = next) { + if (!*cur) + break; + next = index(cur, '/'); + if (next == cur) { + printf("malformed pathname: multiple adjacent slashes\n"); + return(-1); + } + if (next) + *next++ = '\0'; + irec = mpffs_active_index + ino; + if (irec->type != OBJTYPE_DIR) { + printf("Error: non-terminal non-directory\n"); + if (next) + next[-1] = '/'; + return(-1); + } + ino = find_named_child(irec->descend, cur); + if (next) + next[-1] = '/'; + if (!ino) { + printf("Error: pathname component not found\n"); + return(-1); + } + } + return(ino); +} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/cmd_find.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/cmd_find.c Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,25 @@ +#include +#include "types.h" + +void +cmd_find(argbulk) + char *argbulk; +{ + char *argv[2]; + int stat, cont; + u8 *start; + size_t size; + + if (parse_args(argbulk, 1, 1, argv, 0) < 0) + return; + stat = mpffs_find_file(argv[0], &start, &size, &cont); + if (stat < 0) + return; + printf("chunk @%08X size %x\n", (u32)start, (u32)size); + while (cont) { + stat = mpffs_get_segment(cont, &start, &size, &cont); + if (stat < 0) + return; + printf("chunk @%08X size %x\n", (u32)start, (u32)size); + } +} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/findfile.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/findfile.c Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,106 @@ +#include +#include "types.h" +#include "struct.h" +#include "globals.h" +#include "macros.h" + +static u8 * +find_endofchunk(ino) +{ + struct inode *irec = mpffs_active_index + ino; + u8 *p; + int i; + + p = inode_to_dataptr(irec) + irec->len; + for (i = 0; i < 16; i++) { + p--; + if (!*p) + return(p); + if (*p != 0xFF) + break; + } + printf("Error: inode #%x has no valid termination\n", ino); + return(p); /* XXX */ +} + +mpffs_find_file(pathname, startret, sizeret, continue_ret) + char *pathname; + u8 **startret; + size_t *sizeret; + int *continue_ret; +{ + int ino, cont; + struct inode *irec; + u8 *start, *end; + int size; + + ino = mpffs_pathname_to_inode(pathname); + if (ino <= 0) + return(-1); + irec = mpffs_active_index + ino; + if (irec->type != OBJTYPE_FILE) { + printf("Error: %s is not a regular file\n", pathname); + return(-1); + } + start = inode_to_dataptr(irec); + start += strlen(start) + 1; + end = find_endofchunk(ino); + size = end - start; + if (size < 0) + size = 0; + cont = irec->descend; + if (cont == 0xFFFF) + cont = 0; + if (startret) + *startret = start; + if (sizeret) + *sizeret = size; + if (continue_ret) + *continue_ret = cont; + return(0); +} + +mpffs_get_segment(ino, startret, sizeret, continue_ret) + int ino; + u8 **startret; + size_t *sizeret; + int *continue_ret; +{ + int cont; + struct inode *irec; + u8 *start, *end; + int size; + + for (;;) { + irec = mpffs_active_index + ino; + if (irec->type) + break; + if (irec->sibling == 0xFFFF) { + printf("Error: segment inode #%d: deleted and no sibling\n", + ino); + return(-1); + } + ino = irec->sibling; + } + if (irec->type != OBJTYPE_SEGMENT) { + printf("Error: inode #%x is not a segment\n", ino); + return(-1); + } + start = inode_to_dataptr(irec); + end = find_endofchunk(ino); + size = end - start; + if (size <= 0) { + printf("Error: segment inode #%x: bad length\n", ino); + return(-1); + } + cont = irec->descend; + if (cont == 0xFFFF) + cont = 0; + if (startret) + *startret = start; + if (sizeret) + *sizeret = size; + if (continue_ret) + *continue_ret = cont; + return(0); +} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/globals.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/globals.c Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,8 @@ +/* global variables for the MPFFS reader code */ + +#include "types.h" +#include "struct.h" + +struct inode *mpffs_active_index; +int mpffs_root_ino; +int mpffs_init_done; diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/globals.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/globals.h Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,9 @@ +/* global variables for the MPFFS reader code - extern declarations */ + +extern struct inode *mpffs_active_index; +extern int mpffs_root_ino; +extern int mpffs_init_done; + +extern const u32 mpffs_base_addr; +extern const u32 mpffs_sector_size; +extern const int mpffs_nsectors; diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/init.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/init.c Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,74 @@ +#include "types.h" +#include "struct.h" +#include "globals.h" +#include "macros.h" + +static const u8 ffs_sector_signature[6] = {'F', 'f', 's', '#', 0x10, 0x02}; +static const u8 blank_flash_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF}; + +static +find_indexblk() +{ + u32 sector_addr; + u8 *sector_ptr; + int i; + + printf("Looking for MPFFS active index block\n"); + sector_addr = mpffs_base_addr; + for (i = 0; i < mpffs_nsectors; i++) { + sector_ptr = (u8 *) sector_addr; + if (!bcmp(sector_ptr, ffs_sector_signature, 6) && + sector_ptr[8] == 0xAB) { + printf("Found at %08X\n", sector_addr); + mpffs_active_index = (struct inode *) sector_ptr; + return(0); + } + sector_addr += mpffs_sector_size; + } + printf("Error: Not found in any of the %d candidate sectors\n", + mpffs_nsectors); + return(-1); +} + +static +find_rootino() +{ + int ino; + struct inode *irec; + + printf("Looking for the root inode\n"); + for (ino = 1; ; ino++) { + if (ino >= mpffs_sector_size >> 4) { + printf("Error: Hit end of sector, no root inode found\n"); + return(-1); + } + irec = mpffs_active_index + ino; + if (!bcmp((u8 *) irec, blank_flash_line, 16)) { + printf("Error: Hit blank flash, no root inode found\n"); + return(-1); + } + if (irec->type == OBJTYPE_DIR && *inode_to_dataptr(irec) == '/') + break; + } + printf("Found at inode #%x\n", ino); + mpffs_root_ino = ino; + return(0); +} + +mpffs_init() +{ + int stat; + + if (mpffs_init_done) + return(0); + stat = find_indexblk(); + if (stat < 0) + return(stat); + stat = find_rootino(); + if (stat < 0) + return(stat); + mpffs_init_done = 1; + return(0); +} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/macros.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/macros.h Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,1 @@ +#define inode_to_dataptr(i) ((u8 *)mpffs_base_addr + ((i)->dataptr << 4)) diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/rdinmem.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/rdinmem.c Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,42 @@ +#include +#include "types.h" +#include "struct.h" +#include "globals.h" +#include "macros.h" + +mpffs_read_into_ram(pathname, buf, maxlen, lenrtn) + char *pathname; + u8 *buf; + size_t maxlen, *lenrtn; +{ + int stat, cont; + u8 *chunk_start; + size_t chunk_size, real_len, roomleft; + + stat = mpffs_find_file(pathname, &chunk_start, &chunk_size, &cont); + if (stat < 0) + return(stat); + if (chunk_size > maxlen) { +toobig: printf("Error: %s is bigger than the read buffer\n", pathname); + return(-1); + } + real_len = chunk_size; + bcopy(chunk_start, buf, chunk_size); + buf += chunk_size; + roomleft = maxlen - chunk_size; + while (cont) { + stat = mpffs_get_segment(cont, &chunk_start, &chunk_size, + &cont); + if (stat < 0) + return(stat); + if (chunk_size > roomleft) + goto toobig; + real_len += chunk_size; + bcopy(chunk_start, buf, chunk_size); + buf += chunk_size; + roomleft -= chunk_size; + } + if (lenrtn) + *lenrtn = real_len; + return(0); +} diff -r 0848c7f419fd -r 2900fe603f8a target-utils/libtiffs/struct.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/libtiffs/struct.h Sun Jan 12 07:59:00 2014 +0000 @@ -0,0 +1,25 @@ +struct inode { + u16 len; + u8 reserved1; + u8 type; + u16 descend; + u16 sibling; + u32 dataptr; + u16 sequence; + u16 updates; +}; + +#define OBJTYPE_FILE 0xF1 +#define OBJTYPE_DIR 0xF2 +#define OBJTYPE_SEGMENT 0xF4 + +struct journal { + u8 status; + u8 objtype; + u16 this_ino; + u16 link_ptr; + u16 replacee; + u32 location; + u16 size; + u16 repli; /* ??? */ +}; diff -r 0848c7f419fd -r 2900fe603f8a target-utils/pirexplore/Makefile --- a/target-utils/pirexplore/Makefile Tue Jan 07 05:58:11 2014 +0000 +++ b/target-utils/pirexplore/Makefile Sun Jan 12 07:59:00 2014 +0000 @@ -6,7 +6,7 @@ PROG= pirexplore OBJS= crt0.o cmdtab.o ffsparam.o flashid.o lcd.o main.o mygetchar.o rtc.o -LIBS= ../libcommon/libcommon.a ../libload/libload.a ../libmpffs/libmpffs.a \ +LIBS= ../libcommon/libcommon.a ../libload/libload.a ../libtiffs/libtiffs.a \ ../libprintf/libprintf.a LDS= ../env/iram.lds