<p>Vadim Yanitskiy <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/12885">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">firmware/lib: introduce TIFFS filesystem support<br><br>All known TI GSM firmwares implement some kind of flash file system, or FFS.<br>We call it TIFFS (Texas Instruments FFS) because it is TI's invention.<br><br>TIFFS is a file system with a hierarchical directory tree structure, and<br>with Unixy forward-slash-separated, case-sensitive pathnames; the semantics<br>of "what is a file" and "what is a directory" are exactly the same as in<br>UNIX; and TIFFS even supports symlinks, although that support is a little<br>under-developed, and apparently no FFS symlinks were ever used in any<br>production GSM device. Thus the FFS implemented in TI-based GSM devices<br>(modems and "dumbphone" handsets) is really no different from, for example,<br>JFFS2 in embedded Linux systems.<br><br>The FFS in a GSM device typically stores two kinds of content:<br><br>  - Factory data: IMEI, RF calibration values, device make/model/revision<br>    ID strings etc.  These files are expected to be programmed on the<br>    factory production line and not changed afterward.<br><br>  - Dynamic data written into the FFS in normal device operation: contacts,<br>    settings / preferences, call history, received SMS, etc.<br><br>It should be noted that both Compal (Mot C1xx) and Foxconn (Pirelli DP-L10)<br>vendors moved their vital per-unit factory data out of the FFS into their<br>own ad hoc flash data structures, leaving their FFS only for less<br>critical data. However, we do enable TIFFS access for them anyway.<br><br>The location of TIFFS within the flash memory of a given GSM device is<br>defined by the firmware design of that device, but is always some integral<br>number of contiguous flash sectors.<br><br>  - On Motorola/Compal C139/140 phones, the FFS used by the original<br>    proprietary firmware occupies 5 sectors of 64 KiB each (320 KiB<br>    in total), starting at 0x370000. C11x/123 use smaller FFS<br>    configurations, whereas C155/156 seem to have switched to some<br>    other FFS format, different from our familiar TIFFS.<br><br>  - On the Pirelli DP-L10, the FFS used by the original proprietary<br>    firmware occupies 18 sectors of 256 KiB each (for 4.5 MiB in total),<br>    starting at the beginning of the 2nd flash chip select (0x02000000<br>    in the ARM7 address space).<br><br>  - On FCDEV3B (FreeCalypso hardware), the FFS is located in the first<br>    8 sectors (of 256 KiB each) in the 2nd flash chip select bank,<br>    which appears at 0x01800000 in the ARM7 address space.<br><br>  - On the GTA01/02 GSM modem, FFS occupies 7 sectors of 64 KiB each,<br>    starting at flash offset 0x380000.<br><br>For more information, please refer to the FreeCalypso project<br>documentation, from where this great contribution comes from.<br><br>Please note that existing MediaTek targets most likely use different<br>storage format as they have nothing from TI Calypso. Also, we don't<br>(yet) know the location of TIFFS on SE J100i and Compal E99 targets.<br><br>The TIFFS support is needed for the follow-up change, that<br>implements reading of the factory RF calibration values.<br><br>Tweaked (coding style changes) by Vadim Yanitskiy <axilirator@gmail.com><br>Change-Id: If6e212baeb10953129fb0d5253d263567f5e12d6<br>Related: OS#3582<br>---<br>M src/target/firmware/Makefile<br>M src/target/firmware/board/compal_e86/init.c<br>M src/target/firmware/board/compal_e88/init.c<br>M src/target/firmware/board/fcdev3b/init.c<br>M src/target/firmware/board/gta0x/init.c<br>M src/target/firmware/board/pirelli_dpl10/init.c<br>M src/target/firmware/include/string.h<br>A src/target/firmware/include/tiffs.h<br>M src/target/firmware/lib/Makefile<br>A src/target/firmware/lib/index.c<br>A src/target/firmware/lib/memcmp.S<br>A src/target/firmware/lib/strcmp.c<br>A src/target/firmware/tiffs/Makefile<br>A src/target/firmware/tiffs/globals.c<br>A src/target/firmware/tiffs/globals.h<br>A src/target/firmware/tiffs/init.c<br>A src/target/firmware/tiffs/readfile.c<br>17 files changed, 496 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile</span><br><span>index 1196d10..914db6c 100644</span><br><span>--- a/src/target/firmware/Makefile</span><br><span>+++ b/src/target/firmware/Makefile</span><br><span>@@ -107,6 +107,7 @@</span><br><span>             layer1/liblayer1.a \</span><br><span>                 lib/libmini.a \</span><br><span>              comm/libcomm.a \</span><br><span style="color: hsl(120, 100%, 40%);">+              tiffs/libtiffs.a \</span><br><span>           ../../shared/libosmocore/build-target/src/.libs/libosmocore.a \</span><br><span>              ../../shared/libosmocore/build-target/src/gsm/.libs/libosmogsm.a \</span><br><span>           ../../shared/libosmocore/build-target/src/codec/.libs/libosmocodec.a</span><br><span>@@ -123,6 +124,7 @@</span><br><span> -include calypso/Makefile</span><br><span> -include layer1/Makefile</span><br><span> -include comm/Makefile</span><br><span style="color: hsl(120, 100%, 40%);">+-include tiffs/Makefile</span><br><span> -include lib/Makefile</span><br><span> </span><br><span> # Include rules</span><br><span>diff --git a/src/target/firmware/board/compal_e86/init.c b/src/target/firmware/board/compal_e86/init.c</span><br><span>index fed9f85..725f184 100644</span><br><span>--- a/src/target/firmware/board/compal_e86/init.c</span><br><span>+++ b/src/target/firmware/board/compal_e86/init.c</span><br><span>@@ -31,6 +31,7 @@</span><br><span> #include <keypad.h></span><br><span> #include <console.h></span><br><span> #include <flash/cfi_flash.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <tiffs.h></span><br><span> </span><br><span> #include <calypso/irq.h></span><br><span> #include <calypso/clock.h></span><br><span>@@ -146,4 +147,7 @@</span><br><span> </span><br><span>   /* enable LEDB driver of Iota for keypad backlight */</span><br><span>        twl3025_reg_write(AUXLED, 0x02);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Initialize TIFFS reader (5 sectors of 64 KiB each) */</span><br><span style="color: hsl(120, 100%, 40%);">+      tiffs_init(0x370000, 0x10000, 5);</span><br><span> }</span><br><span>diff --git a/src/target/firmware/board/compal_e88/init.c b/src/target/firmware/board/compal_e88/init.c</span><br><span>index 04ae458..956f7dc 100755</span><br><span>--- a/src/target/firmware/board/compal_e88/init.c</span><br><span>+++ b/src/target/firmware/board/compal_e88/init.c</span><br><span>@@ -30,6 +30,7 @@</span><br><span> #include <keypad.h></span><br><span> #include <console.h></span><br><span> #include <flash/cfi_flash.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <tiffs.h></span><br><span> </span><br><span> #include <calypso/irq.h></span><br><span> #include <calypso/clock.h></span><br><span>@@ -142,4 +143,7 @@</span><br><span> </span><br><span>   /* Initialize the charging controller */</span><br><span>     battery_compal_e88_init();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Initialize TIFFS reader (6 sectors of 8 KiB each) */</span><br><span style="color: hsl(120, 100%, 40%);">+       tiffs_init(0x001f0000, 0x2000, 6);</span><br><span> }</span><br><span>diff --git a/src/target/firmware/board/fcdev3b/init.c b/src/target/firmware/board/fcdev3b/init.c</span><br><span>index 92be667..c070536 100644</span><br><span>--- a/src/target/firmware/board/fcdev3b/init.c</span><br><span>+++ b/src/target/firmware/board/fcdev3b/init.c</span><br><span>@@ -32,6 +32,7 @@</span><br><span> #include <keypad.h></span><br><span> #include <console.h></span><br><span> #include <flash/cfi_flash.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <tiffs.h></span><br><span> </span><br><span> #include <calypso/irq.h></span><br><span> #include <calypso/clock.h></span><br><span>@@ -138,4 +139,7 @@</span><br><span> </span><br><span>      /* Initialize ABB driver (uses SPI) */</span><br><span>       twl3025_init();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Initialize TIFFS reader (8 sectors of 256 KiB each) */</span><br><span style="color: hsl(120, 100%, 40%);">+     tiffs_init(0x01800000, 0x40000, 8);</span><br><span> }</span><br><span>diff --git a/src/target/firmware/board/gta0x/init.c b/src/target/firmware/board/gta0x/init.c</span><br><span>index b93f79c..7fba756 100644</span><br><span>--- a/src/target/firmware/board/gta0x/init.c</span><br><span>+++ b/src/target/firmware/board/gta0x/init.c</span><br><span>@@ -30,6 +30,7 @@</span><br><span> #include <keypad.h></span><br><span> #include <console.h></span><br><span> #include <flash/cfi_flash.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <tiffs.h></span><br><span> </span><br><span> #include <calypso/irq.h></span><br><span> #include <calypso/clock.h></span><br><span>@@ -132,4 +133,7 @@</span><br><span> </span><br><span>     /* Initialize ABB driver (uses SPI) */</span><br><span>       twl3025_init();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Initialize TIFFS reader (7 sectors of 64 KiB each) */</span><br><span style="color: hsl(120, 100%, 40%);">+      tiffs_init(0x380000, 0x10000, 7);</span><br><span> }</span><br><span>diff --git a/src/target/firmware/board/pirelli_dpl10/init.c b/src/target/firmware/board/pirelli_dpl10/init.c</span><br><span>index da23308..1af6e7c 100644</span><br><span>--- a/src/target/firmware/board/pirelli_dpl10/init.c</span><br><span>+++ b/src/target/firmware/board/pirelli_dpl10/init.c</span><br><span>@@ -31,6 +31,7 @@</span><br><span> #include <keypad.h></span><br><span> #include <console.h></span><br><span> #include <flash/cfi_flash.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <tiffs.h></span><br><span> </span><br><span> #include <calypso/irq.h></span><br><span> #include <calypso/clock.h></span><br><span>@@ -156,4 +157,7 @@</span><br><span> </span><br><span>       /* enable LEDB driver of Iota for keypad backlight */</span><br><span>        twl3025_reg_write(AUXLED, 0x02);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Initialize TIFFS reader (18 sectors of 256 KiB each) */</span><br><span style="color: hsl(120, 100%, 40%);">+    tiffs_init(0x02000000, 0x40000, 18);</span><br><span> }</span><br><span>diff --git a/src/target/firmware/include/string.h b/src/target/firmware/include/string.h</span><br><span>index f060659..ecef13d 100644</span><br><span>--- a/src/target/firmware/include/string.h</span><br><span>+++ b/src/target/firmware/include/string.h</span><br><span>@@ -9,4 +9,7 @@</span><br><span> void *memset(void *s, int c, size_t n);</span><br><span> void *memcpy(void *dest, const void *src, size_t n);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int memcmp(const void *s1, const void *s2, size_t n);</span><br><span style="color: hsl(120, 100%, 40%);">+int strcmp(const char *s1, const char *s2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif</span><br><span>diff --git a/src/target/firmware/include/tiffs.h b/src/target/firmware/include/tiffs.h</span><br><span>new file mode 100644</span><br><span>index 0000000..4713c4e</span><br><span>--- /dev/null</span><br><span>+++ b/src/target/firmware/include/tiffs.h</span><br><span>@@ -0,0 +1,33 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * The external API for the TIFFS reader library (libtiffs).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * For the file reading functions, the return code is 0 if the file wasn't</span><br><span style="color: hsl(120, 100%, 40%);">+ * found or there is no valid FFS (no error msg printed), 1 if the file was</span><br><span style="color: hsl(120, 100%, 40%);">+ * found and read successfully, or negative if some other error(s) occurred</span><br><span style="color: hsl(120, 100%, 40%);">+ * (error msg printed internally).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define INODE_TO_DATAPTR(i) \</span><br><span style="color: hsl(120, 100%, 40%);">+     ((uint8_t *)tiffs_base_addr + ((i)->dataptr << 4))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define  TIFFS_OBJTYPE_FILE      0xF1</span><br><span style="color: hsl(120, 100%, 40%);">+#define   TIFFS_OBJTYPE_DIR       0xF2</span><br><span style="color: hsl(120, 100%, 40%);">+#define   TIFFS_OBJTYPE_SEGMENT   0xF4</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct tiffs_inode {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint16_t        len;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t         reserved1;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t         type;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t        descend;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t        sibling;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t        dataptr;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t        sequence;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint16_t        updates;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int tiffs_init(uint32_t base_addr, uint32_t sector_size, unsigned nsectors);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int tiffs_read_file_maxlen(const char *pathname, uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                           size_t maxlen, size_t *lenrtn);</span><br><span style="color: hsl(120, 100%, 40%);">+int tiffs_read_file_fixedlen(const char *pathname, uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                       size_t expect_len);</span><br><span>diff --git a/src/target/firmware/lib/Makefile b/src/target/firmware/lib/Makefile</span><br><span>index a2a6d45..7546198 100644</span><br><span>--- a/src/target/firmware/lib/Makefile</span><br><span>+++ b/src/target/firmware/lib/Makefile</span><br><span>@@ -2,6 +2,7 @@</span><br><span> LIBRARIES+=mini</span><br><span> LIB_mini_DIR=lib</span><br><span> LIB_mini_SRCS=vsprintf.c string.c ctype.c printf.c console.c ctors.c \</span><br><span style="color: hsl(0, 100%, 40%);">-                changebit.S clearbit.S delay.c div64.S lib1funcs.S memcpy.S memset.S setbit.S testchangebit.S testclearbit.S testsetbit.S</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+             changebit.S clearbit.S delay.c div64.S lib1funcs.S memcpy.S \</span><br><span style="color: hsl(120, 100%, 40%);">+         memset.S setbit.S testchangebit.S testclearbit.S testsetbit.S \</span><br><span style="color: hsl(120, 100%, 40%);">+               memcmp.S index.c strcmp.c</span><br><span> </span><br><span>diff --git a/src/target/firmware/lib/index.c b/src/target/firmware/lib/index.c</span><br><span>new file mode 100644</span><br><span>index 0000000..bb304c0</span><br><span>--- /dev/null</span><br><span>+++ b/src/target/firmware/lib/index.c</span><br><span>@@ -0,0 +1,12 @@</span><br><span style="color: hsl(120, 100%, 40%);">+char *</span><br><span style="color: hsl(120, 100%, 40%);">+index(p, ch)</span><br><span style="color: hsl(120, 100%, 40%);">+       register char *p, ch;</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      for (;; ++p) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (*p == ch)</span><br><span style="color: hsl(120, 100%, 40%);">+                 return(p);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!*p)</span><br><span style="color: hsl(120, 100%, 40%);">+                      return((char *)0);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* NOTREACHED */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/target/firmware/lib/memcmp.S b/src/target/firmware/lib/memcmp.S</span><br><span>new file mode 100644</span><br><span>index 0000000..c60b170</span><br><span>--- /dev/null</span><br><span>+++ b/src/target/firmware/lib/memcmp.S</span><br><span>@@ -0,0 +1,18 @@</span><br><span style="color: hsl(120, 100%, 40%);">+    .text</span><br><span style="color: hsl(120, 100%, 40%);">+ .code   32</span><br><span style="color: hsl(120, 100%, 40%);">+    .globl  memcmp</span><br><span style="color: hsl(120, 100%, 40%);">+memcmp:</span><br><span style="color: hsl(120, 100%, 40%);">+       cmp     r2, #0</span><br><span style="color: hsl(120, 100%, 40%);">+        beq     zero_len_out</span><br><span style="color: hsl(120, 100%, 40%);">+  mov     r3, r0</span><br><span style="color: hsl(120, 100%, 40%);">+1:      ldrb    r0, [r3], #1</span><br><span style="color: hsl(120, 100%, 40%);">+  ldrb    r12, [r1], #1</span><br><span style="color: hsl(120, 100%, 40%);">+ subs    r0, r0, r12</span><br><span style="color: hsl(120, 100%, 40%);">+   bxne    lr</span><br><span style="color: hsl(120, 100%, 40%);">+    subs    r2, r2, #1</span><br><span style="color: hsl(120, 100%, 40%);">+    bne     1b</span><br><span style="color: hsl(120, 100%, 40%);">+    bx      lr</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+zero_len_out:</span><br><span style="color: hsl(120, 100%, 40%);">+   mov     r0, #0</span><br><span style="color: hsl(120, 100%, 40%);">+        bx      lr</span><br><span>diff --git a/src/target/firmware/lib/strcmp.c b/src/target/firmware/lib/strcmp.c</span><br><span>new file mode 100644</span><br><span>index 0000000..9a7fa81</span><br><span>--- /dev/null</span><br><span>+++ b/src/target/firmware/lib/strcmp.c</span><br><span>@@ -0,0 +1,12 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+strcmp(s1, s2)</span><br><span style="color: hsl(120, 100%, 40%);">+        register char *s1, *s2;</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    while (*s1 == *s2++)</span><br><span style="color: hsl(120, 100%, 40%);">+          if (*s1++=='\0')</span><br><span style="color: hsl(120, 100%, 40%);">+                      return(0);</span><br><span style="color: hsl(120, 100%, 40%);">+    return(*s1 - *--s2);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/target/firmware/tiffs/Makefile b/src/target/firmware/tiffs/Makefile</span><br><span>new file mode 100644</span><br><span>index 0000000..6ded9e8</span><br><span>--- /dev/null</span><br><span>+++ b/src/target/firmware/tiffs/Makefile</span><br><span>@@ -0,0 +1,5 @@</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+LIBRARIES+=tiffs</span><br><span style="color: hsl(120, 100%, 40%);">+LIB_tiffs_DIR=tiffs</span><br><span style="color: hsl(120, 100%, 40%);">+LIB_tiffs_SRCS=globals.c init.c readfile.c</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/src/target/firmware/tiffs/globals.c b/src/target/firmware/tiffs/globals.c</span><br><span>new file mode 100644</span><br><span>index 0000000..ffbba42</span><br><span>--- /dev/null</span><br><span>+++ b/src/target/firmware/tiffs/globals.c</span><br><span>@@ -0,0 +1,12 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* global variables for the TIFFS reader code */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "globals.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t tiffs_base_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t tiffs_sector_size;</span><br><span style="color: hsl(120, 100%, 40%);">+unsigned tiffs_nsectors;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct tiffs_inode *tiffs_active_index;</span><br><span style="color: hsl(120, 100%, 40%);">+int tiffs_root_ino;</span><br><span style="color: hsl(120, 100%, 40%);">+int tiffs_init_done;</span><br><span>diff --git a/src/target/firmware/tiffs/globals.h b/src/target/firmware/tiffs/globals.h</span><br><span>new file mode 100644</span><br><span>index 0000000..7c64693</span><br><span>--- /dev/null</span><br><span>+++ b/src/target/firmware/tiffs/globals.h</span><br><span>@@ -0,0 +1,9 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* global variables for the TIFFS reader code - extern declarations */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern uint32_t tiffs_base_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+extern uint32_t tiffs_sector_size;</span><br><span style="color: hsl(120, 100%, 40%);">+extern unsigned tiffs_nsectors;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern struct tiffs_inode *tiffs_active_index;</span><br><span style="color: hsl(120, 100%, 40%);">+extern int tiffs_root_ino;</span><br><span style="color: hsl(120, 100%, 40%);">+extern int tiffs_init_done;</span><br><span>diff --git a/src/target/firmware/tiffs/init.c b/src/target/firmware/tiffs/init.c</span><br><span>new file mode 100644</span><br><span>index 0000000..6a3b48a</span><br><span>--- /dev/null</span><br><span>+++ b/src/target/firmware/tiffs/init.c</span><br><span>@@ -0,0 +1,103 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* TIFFS (TI Flash File System) reader implementation */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2017 by Mychaela Falconia <mychaela.falconia@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * Tweaked (coding style changes) by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <tiffs.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "globals.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Each flash sector used for TIFFS begins with this 6-byte signature */</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t ffs_sector_signature[6] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   'F', 'f', 's', '#', 0x10, 0x02</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int find_indexblk(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t sector_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *sector_ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ sector_addr = tiffs_base_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < tiffs_nsectors; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             sector_ptr = (uint8_t *) sector_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!memcmp(sector_ptr, ffs_sector_signature, 6)</span><br><span style="color: hsl(120, 100%, 40%);">+                  && sector_ptr[8] == 0xAB) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       printf("Found TIFFS active index block "</span><br><span style="color: hsl(120, 100%, 40%);">+                            "at 0x%" PRIx32 "\n", sector_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+                       tiffs_active_index = (struct tiffs_inode *) sector_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+                      return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             sector_addr += tiffs_sector_size;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   puts("TIFFS error: no active index block found\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int find_rootino(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct tiffs_inode *irec;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned ino = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while (++ino < tiffs_sector_size >> 4) {</span><br><span style="color: hsl(120, 100%, 40%);">+             irec = tiffs_active_index + ino;</span><br><span style="color: hsl(120, 100%, 40%);">+              if (irec->type != TIFFS_OBJTYPE_DIR)</span><br><span style="color: hsl(120, 100%, 40%);">+                       continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (*INODE_TO_DATAPTR(irec) != '/')</span><br><span style="color: hsl(120, 100%, 40%);">+                   continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           printf("Found TIFFS root inode at #%x\n", ino);</span><br><span style="color: hsl(120, 100%, 40%);">+             tiffs_root_ino = ino;</span><br><span style="color: hsl(120, 100%, 40%);">+         return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   puts("TIFFS error: no root inode found\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int tiffs_init(uint32_t base_addr, uint32_t sector_size, unsigned nsectors)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("Looking for TIFFS (TI Flash File System) header at "</span><br><span style="color: hsl(120, 100%, 40%);">+                "0x%" PRIx32 ", %u sectors of 0x%" PRIx32 " bytes\n",</span><br><span style="color: hsl(120, 100%, 40%);">+           base_addr, nsectors, sector_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  tiffs_base_addr = base_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+  tiffs_sector_size = sector_size;</span><br><span style="color: hsl(120, 100%, 40%);">+      tiffs_nsectors = nsectors;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = find_indexblk();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = find_rootino();</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  tiffs_init_done = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/target/firmware/tiffs/readfile.c b/src/target/firmware/tiffs/readfile.c</span><br><span>new file mode 100644</span><br><span>index 0000000..f3e916f</span><br><span>--- /dev/null</span><br><span>+++ b/src/target/firmware/tiffs/readfile.c</span><br><span>@@ -0,0 +1,264 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* TIFFS (TI Flash File System) reader implementation */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2017 by Mychaela Falconia <mychaela.falconia@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * Tweaked (coding style changes) by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <tiffs.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "globals.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern char *index();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define  MAX_FN_COMPONENT        20</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static unsigned find_named_child(unsigned start, const char *seekname)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct tiffs_inode *irec;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned ino;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       for (ino = start; ino != 0xFFFF; ino = irec->sibling) {</span><br><span style="color: hsl(120, 100%, 40%);">+            irec = tiffs_active_index + ino;</span><br><span style="color: hsl(120, 100%, 40%);">+              if (!irec->type)</span><br><span style="color: hsl(120, 100%, 40%);">+                   continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!strcmp((const char *) INODE_TO_DATAPTR(irec), seekname))</span><br><span style="color: hsl(120, 100%, 40%);">+                 return ino;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int pathname_to_inode(const char *pathname)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char seekname[MAX_FN_COMPONENT + 1];</span><br><span style="color: hsl(120, 100%, 40%);">+  struct tiffs_inode *irec;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *cur, *next;</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned ino, namelen;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      cur = pathname;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (*cur == '/')</span><br><span style="color: hsl(120, 100%, 40%);">+              cur++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (ino = tiffs_root_ino; cur; cur = next) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!*cur)</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              next = index(cur, '/');</span><br><span style="color: hsl(120, 100%, 40%);">+               if (next == cur) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    puts("Malformed TIFFS pathname: multiple adjacent slashes\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                      return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            } else if (next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    namelen = next - cur;</span><br><span style="color: hsl(120, 100%, 40%);">+                 next++;</span><br><span style="color: hsl(120, 100%, 40%);">+               } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      namelen = strlen(cur);</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (namelen > MAX_FN_COMPONENT) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  puts("Malformed TIFFS pathname: component name too long\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                        return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(seekname, cur, namelen);</span><br><span style="color: hsl(120, 100%, 40%);">+               seekname[namelen] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           irec = tiffs_active_index + ino;</span><br><span style="color: hsl(120, 100%, 40%);">+              if (irec->type != TIFFS_OBJTYPE_DIR) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* printf("Error: non-terminal non-directory\n"); */</span><br><span style="color: hsl(120, 100%, 40%);">+                        return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             ino = find_named_child(irec->descend, seekname);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!ino) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* printf("Error: pathname component not found\n"); */</span><br><span style="color: hsl(120, 100%, 40%);">+                      return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return ino;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t *find_endofchunk(int ino)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct tiffs_inode *irec;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t *ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      irec = tiffs_active_index + ino;</span><br><span style="color: hsl(120, 100%, 40%);">+      ptr = INODE_TO_DATAPTR(irec) + irec->len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < 16; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ptr--;</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!*ptr)</span><br><span style="color: hsl(120, 100%, 40%);">+                    return ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (*ptr != 0xFF)</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   printf("TIFFS error: inode #%x has no valid termination\n", ino);</span><br><span style="color: hsl(120, 100%, 40%);">+   return ptr; /* XXX */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int get_file_head(const char *pathname, uint8_t **startret,</span><br><span style="color: hsl(120, 100%, 40%);">+                         size_t *sizeret, int *continue_ret)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct tiffs_inode *irec;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t *start, *end;</span><br><span style="color: hsl(120, 100%, 40%);">+ int ino, cont, size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ino = pathname_to_inode(pathname);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (ino <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+              return ino;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ irec = tiffs_active_index + ino;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (irec->type != TIFFS_OBJTYPE_FILE) {</span><br><span style="color: hsl(120, 100%, 40%);">+            printf("TIFFS error: '%s' is not a regular file\n", pathname);</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   start = INODE_TO_DATAPTR(irec);</span><br><span style="color: hsl(120, 100%, 40%);">+       start += strlen((const char *) start) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    end = find_endofchunk(ino);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size = end - start;</span><br><span style="color: hsl(120, 100%, 40%);">+   if (size < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+              size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   cont = irec->descend;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (cont == 0xFFFF)</span><br><span style="color: hsl(120, 100%, 40%);">+           cont = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (startret)</span><br><span style="color: hsl(120, 100%, 40%);">+         *startret = start;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (sizeret)</span><br><span style="color: hsl(120, 100%, 40%);">+          *sizeret = size;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (continue_ret)</span><br><span style="color: hsl(120, 100%, 40%);">+             *continue_ret = cont;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int get_segment(int ino, uint8_t **startret,</span><br><span style="color: hsl(120, 100%, 40%);">+                  size_t *sizeret, int *continue_ret)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct tiffs_inode *irec;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t *start, *end;</span><br><span style="color: hsl(120, 100%, 40%);">+ int cont, size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (;;) {</span><br><span style="color: hsl(120, 100%, 40%);">+            irec = tiffs_active_index + ino;</span><br><span style="color: hsl(120, 100%, 40%);">+              if (irec->type)</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                if (irec->sibling == 0xFFFF) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("TIFFS error: segment inode #%d: "</span><br><span style="color: hsl(120, 100%, 40%);">+                           "deleted and no sibling\n", ino);</span><br><span style="color: hsl(120, 100%, 40%);">+                   return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             ino = irec->sibling;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (irec->type != TIFFS_OBJTYPE_SEGMENT) {</span><br><span style="color: hsl(120, 100%, 40%);">+         printf("TIFFS error: inode #%x is not a segment\n", ino);</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   start = INODE_TO_DATAPTR(irec);</span><br><span style="color: hsl(120, 100%, 40%);">+       end = find_endofchunk(ino);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size = end - start;</span><br><span style="color: hsl(120, 100%, 40%);">+   if (size <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           printf("TIFFS error: segment inode #%x has bad length\n", ino);</span><br><span style="color: hsl(120, 100%, 40%);">+             return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   cont = irec->descend;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (cont == 0xFFFF)</span><br><span style="color: hsl(120, 100%, 40%);">+           cont = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (startret)</span><br><span style="color: hsl(120, 100%, 40%);">+         *startret = start;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (sizeret)</span><br><span style="color: hsl(120, 100%, 40%);">+          *sizeret = size;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (continue_ret)</span><br><span style="color: hsl(120, 100%, 40%);">+             *continue_ret = cont;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int tiffs_read_file_maxlen(const char *pathname, uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                           size_t maxlen, size_t *lenrtn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t chunk_size, real_len, roomleft;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t *chunk_start;</span><br><span style="color: hsl(120, 100%, 40%);">+ int stat, cont;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!tiffs_init_done) {</span><br><span style="color: hsl(120, 100%, 40%);">+               puts("TIFFS reader is not initialized\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   stat = get_file_head(pathname, &chunk_start, &chunk_size, &cont);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (stat <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+             return stat;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (chunk_size > maxlen) {</span><br><span style="color: hsl(120, 100%, 40%);">+toobig:          printf("TIFFS error: '%s' is bigger than the read buffer\n", pathname);</span><br><span style="color: hsl(120, 100%, 40%);">+             return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   real_len = chunk_size;</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(buf, chunk_start, chunk_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ buf += chunk_size;</span><br><span style="color: hsl(120, 100%, 40%);">+    roomleft = maxlen - chunk_size;</span><br><span style="color: hsl(120, 100%, 40%);">+       while (cont) {</span><br><span style="color: hsl(120, 100%, 40%);">+                stat = get_segment(cont, &chunk_start, &chunk_size, &cont);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (stat < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                      return stat;</span><br><span style="color: hsl(120, 100%, 40%);">+          if (chunk_size > roomleft)</span><br><span style="color: hsl(120, 100%, 40%);">+                 goto toobig;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                real_len += chunk_size;</span><br><span style="color: hsl(120, 100%, 40%);">+               memcpy(buf, chunk_start, chunk_size);</span><br><span style="color: hsl(120, 100%, 40%);">+         buf += chunk_size;</span><br><span style="color: hsl(120, 100%, 40%);">+            roomleft -= chunk_size;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (lenrtn)</span><br><span style="color: hsl(120, 100%, 40%);">+           *lenrtn = real_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int tiffs_read_file_fixedlen(const char *pathname, uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                           size_t expect_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    size_t real_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = tiffs_read_file_maxlen(pathname, buf, expect_len, &real_len);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+               return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (real_len != expect_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+         printf("TIFFS error: '%s' has the wrong length\n", pathname);</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/12885">change 12885</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/12885"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmocom-bb </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: If6e212baeb10953129fb0d5253d263567f5e12d6 </div>
<div style="display:none"> Gerrit-Change-Number: 12885 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: Vadim Yanitskiy <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: Max <msuraev@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Vadim Yanitskiy <axilirator@gmail.com> </div>