Change in osmocom-bb[master]: firmware/lib: introduce TIFFS filesystem support

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Vadim Yanitskiy gerrit-no-reply at lists.osmocom.org
Wed Feb 20 08:18:16 UTC 2019


Vadim Yanitskiy has submitted this change and it was merged. ( https://gerrit.osmocom.org/12885 )

Change subject: firmware/lib: introduce TIFFS filesystem support
......................................................................

firmware/lib: introduce TIFFS filesystem support

All known TI GSM firmwares implement some kind of flash file system, or FFS.
We call it TIFFS (Texas Instruments FFS) because it is TI's invention.

TIFFS is a file system with a hierarchical directory tree structure, and
with Unixy forward-slash-separated, case-sensitive pathnames; the semantics
of "what is a file" and "what is a directory" are exactly the same as in
UNIX; and TIFFS even supports symlinks, although that support is a little
under-developed, and apparently no FFS symlinks were ever used in any
production GSM device. Thus the FFS implemented in TI-based GSM devices
(modems and "dumbphone" handsets) is really no different from, for example,
JFFS2 in embedded Linux systems.

The FFS in a GSM device typically stores two kinds of content:

  - Factory data: IMEI, RF calibration values, device make/model/revision
    ID strings etc.  These files are expected to be programmed on the
    factory production line and not changed afterward.

  - Dynamic data written into the FFS in normal device operation: contacts,
    settings / preferences, call history, received SMS, etc.

It should be noted that both Compal (Mot C1xx) and Foxconn (Pirelli DP-L10)
vendors moved their vital per-unit factory data out of the FFS into their
own ad hoc flash data structures, leaving their FFS only for less
critical data. However, we do enable TIFFS access for them anyway.

The location of TIFFS within the flash memory of a given GSM device is
defined by the firmware design of that device, but is always some integral
number of contiguous flash sectors.

  - On Motorola/Compal C139/140 phones, the FFS used by the original
    proprietary firmware occupies 5 sectors of 64 KiB each (320 KiB
    in total), starting at 0x370000. C11x/123 use smaller FFS
    configurations, whereas C155/156 seem to have switched to some
    other FFS format, different from our familiar TIFFS.

  - On the Pirelli DP-L10, the FFS used by the original proprietary
    firmware occupies 18 sectors of 256 KiB each (for 4.5 MiB in total),
    starting at the beginning of the 2nd flash chip select (0x02000000
    in the ARM7 address space).

  - On FCDEV3B (FreeCalypso hardware), the FFS is located in the first
    8 sectors (of 256 KiB each) in the 2nd flash chip select bank,
    which appears at 0x01800000 in the ARM7 address space.

  - On the GTA01/02 GSM modem, FFS occupies 7 sectors of 64 KiB each,
    starting at flash offset 0x380000.

For more information, please refer to the FreeCalypso project
documentation, from where this great contribution comes from.

Please note that existing MediaTek targets most likely use different
storage format as they have nothing from TI Calypso. Also, we don't
(yet) know the location of TIFFS on SE J100i and Compal E99 targets.

The TIFFS support is needed for the follow-up change, that
implements reading of the factory RF calibration values.

Tweaked (coding style changes) by Vadim Yanitskiy <axilirator at gmail.com>
Change-Id: If6e212baeb10953129fb0d5253d263567f5e12d6
Related: OS#3582
---
M src/target/firmware/Makefile
M src/target/firmware/board/compal_e86/init.c
M src/target/firmware/board/compal_e88/init.c
M src/target/firmware/board/fcdev3b/init.c
M src/target/firmware/board/gta0x/init.c
M src/target/firmware/board/pirelli_dpl10/init.c
M src/target/firmware/include/string.h
A src/target/firmware/include/tiffs.h
M src/target/firmware/lib/Makefile
A src/target/firmware/lib/index.c
A src/target/firmware/lib/memcmp.S
A src/target/firmware/lib/strcmp.c
A src/target/firmware/tiffs/Makefile
A src/target/firmware/tiffs/globals.c
A src/target/firmware/tiffs/globals.h
A src/target/firmware/tiffs/init.c
A src/target/firmware/tiffs/readfile.c
17 files changed, 496 insertions(+), 2 deletions(-)

Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved



diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile
index 1196d10..914db6c 100644
--- a/src/target/firmware/Makefile
+++ b/src/target/firmware/Makefile
@@ -107,6 +107,7 @@
 		layer1/liblayer1.a \
 		lib/libmini.a \
 		comm/libcomm.a \
+		tiffs/libtiffs.a \
 		../../shared/libosmocore/build-target/src/.libs/libosmocore.a \
 		../../shared/libosmocore/build-target/src/gsm/.libs/libosmogsm.a \
 		../../shared/libosmocore/build-target/src/codec/.libs/libosmocodec.a
@@ -123,6 +124,7 @@
 -include calypso/Makefile
 -include layer1/Makefile
 -include comm/Makefile
+-include tiffs/Makefile
 -include lib/Makefile
 
 # Include rules
diff --git a/src/target/firmware/board/compal_e86/init.c b/src/target/firmware/board/compal_e86/init.c
index fed9f85..725f184 100644
--- a/src/target/firmware/board/compal_e86/init.c
+++ b/src/target/firmware/board/compal_e86/init.c
@@ -31,6 +31,7 @@
 #include <keypad.h>
 #include <console.h>
 #include <flash/cfi_flash.h>
+#include <tiffs.h>
 
 #include <calypso/irq.h>
 #include <calypso/clock.h>
@@ -146,4 +147,7 @@
 
 	/* enable LEDB driver of Iota for keypad backlight */
 	twl3025_reg_write(AUXLED, 0x02);
+
+	/* Initialize TIFFS reader (5 sectors of 64 KiB each) */
+	tiffs_init(0x370000, 0x10000, 5);
 }
diff --git a/src/target/firmware/board/compal_e88/init.c b/src/target/firmware/board/compal_e88/init.c
index 04ae458..956f7dc 100755
--- a/src/target/firmware/board/compal_e88/init.c
+++ b/src/target/firmware/board/compal_e88/init.c
@@ -30,6 +30,7 @@
 #include <keypad.h>
 #include <console.h>
 #include <flash/cfi_flash.h>
+#include <tiffs.h>
 
 #include <calypso/irq.h>
 #include <calypso/clock.h>
@@ -142,4 +143,7 @@
 
 	/* Initialize the charging controller */
 	battery_compal_e88_init();
+
+	/* Initialize TIFFS reader (6 sectors of 8 KiB each) */
+	tiffs_init(0x001f0000, 0x2000, 6);
 }
diff --git a/src/target/firmware/board/fcdev3b/init.c b/src/target/firmware/board/fcdev3b/init.c
index 92be667..c070536 100644
--- a/src/target/firmware/board/fcdev3b/init.c
+++ b/src/target/firmware/board/fcdev3b/init.c
@@ -32,6 +32,7 @@
 #include <keypad.h>
 #include <console.h>
 #include <flash/cfi_flash.h>
+#include <tiffs.h>
 
 #include <calypso/irq.h>
 #include <calypso/clock.h>
@@ -138,4 +139,7 @@
 
 	/* Initialize ABB driver (uses SPI) */
 	twl3025_init();
+
+	/* Initialize TIFFS reader (8 sectors of 256 KiB each) */
+	tiffs_init(0x01800000, 0x40000, 8);
 }
diff --git a/src/target/firmware/board/gta0x/init.c b/src/target/firmware/board/gta0x/init.c
index b93f79c..7fba756 100644
--- a/src/target/firmware/board/gta0x/init.c
+++ b/src/target/firmware/board/gta0x/init.c
@@ -30,6 +30,7 @@
 #include <keypad.h>
 #include <console.h>
 #include <flash/cfi_flash.h>
+#include <tiffs.h>
 
 #include <calypso/irq.h>
 #include <calypso/clock.h>
@@ -132,4 +133,7 @@
 
 	/* Initialize ABB driver (uses SPI) */
 	twl3025_init();
+
+	/* Initialize TIFFS reader (7 sectors of 64 KiB each) */
+	tiffs_init(0x380000, 0x10000, 7);
 }
diff --git a/src/target/firmware/board/pirelli_dpl10/init.c b/src/target/firmware/board/pirelli_dpl10/init.c
index da23308..1af6e7c 100644
--- a/src/target/firmware/board/pirelli_dpl10/init.c
+++ b/src/target/firmware/board/pirelli_dpl10/init.c
@@ -31,6 +31,7 @@
 #include <keypad.h>
 #include <console.h>
 #include <flash/cfi_flash.h>
+#include <tiffs.h>
 
 #include <calypso/irq.h>
 #include <calypso/clock.h>
@@ -156,4 +157,7 @@
 
 	/* enable LEDB driver of Iota for keypad backlight */
 	twl3025_reg_write(AUXLED, 0x02);
+
+	/* Initialize TIFFS reader (18 sectors of 256 KiB each) */
+	tiffs_init(0x02000000, 0x40000, 18);
 }
diff --git a/src/target/firmware/include/string.h b/src/target/firmware/include/string.h
index f060659..ecef13d 100644
--- a/src/target/firmware/include/string.h
+++ b/src/target/firmware/include/string.h
@@ -9,4 +9,7 @@
 void *memset(void *s, int c, size_t n);
 void *memcpy(void *dest, const void *src, size_t n);
 
+int memcmp(const void *s1, const void *s2, size_t n);
+int strcmp(const char *s1, const char *s2);
+
 #endif
diff --git a/src/target/firmware/include/tiffs.h b/src/target/firmware/include/tiffs.h
new file mode 100644
index 0000000..4713c4e
--- /dev/null
+++ b/src/target/firmware/include/tiffs.h
@@ -0,0 +1,33 @@
+/*
+ * The external API for the TIFFS reader library (libtiffs).
+ *
+ * For the file reading functions, the return code is 0 if the file wasn't
+ * found or there is no valid FFS (no error msg printed), 1 if the file was
+ * found and read successfully, or negative if some other error(s) occurred
+ * (error msg printed internally).
+ */
+
+#define INODE_TO_DATAPTR(i) \
+	((uint8_t *)tiffs_base_addr + ((i)->dataptr << 4))
+
+#define	TIFFS_OBJTYPE_FILE	0xF1
+#define	TIFFS_OBJTYPE_DIR	0xF2
+#define	TIFFS_OBJTYPE_SEGMENT	0xF4
+
+struct tiffs_inode {
+	uint16_t	len;
+	uint8_t		reserved1;
+	uint8_t		type;
+	uint16_t	descend;
+	uint16_t	sibling;
+	uint32_t	dataptr;
+	uint16_t	sequence;
+	uint16_t	updates;
+};
+
+int tiffs_init(uint32_t base_addr, uint32_t sector_size, unsigned nsectors);
+
+int tiffs_read_file_maxlen(const char *pathname, uint8_t *buf,
+			   size_t maxlen, size_t *lenrtn);
+int tiffs_read_file_fixedlen(const char *pathname, uint8_t *buf,
+			     size_t expect_len);
diff --git a/src/target/firmware/lib/Makefile b/src/target/firmware/lib/Makefile
index a2a6d45..7546198 100644
--- a/src/target/firmware/lib/Makefile
+++ b/src/target/firmware/lib/Makefile
@@ -2,6 +2,7 @@
 LIBRARIES+=mini
 LIB_mini_DIR=lib
 LIB_mini_SRCS=vsprintf.c string.c ctype.c printf.c console.c ctors.c \
-		changebit.S clearbit.S delay.c div64.S lib1funcs.S memcpy.S memset.S setbit.S testchangebit.S testclearbit.S testsetbit.S
-
+		changebit.S clearbit.S delay.c div64.S lib1funcs.S memcpy.S \
+		memset.S setbit.S testchangebit.S testclearbit.S testsetbit.S \
+		memcmp.S index.c strcmp.c
 
diff --git a/src/target/firmware/lib/index.c b/src/target/firmware/lib/index.c
new file mode 100644
index 0000000..bb304c0
--- /dev/null
+++ b/src/target/firmware/lib/index.c
@@ -0,0 +1,12 @@
+char *
+index(p, ch)
+	register char *p, ch;
+{
+	for (;; ++p) {
+		if (*p == ch)
+			return(p);
+		if (!*p)
+			return((char *)0);
+	}
+	/* NOTREACHED */
+}
diff --git a/src/target/firmware/lib/memcmp.S b/src/target/firmware/lib/memcmp.S
new file mode 100644
index 0000000..c60b170
--- /dev/null
+++ b/src/target/firmware/lib/memcmp.S
@@ -0,0 +1,18 @@
+	.text
+	.code	32
+	.globl	memcmp
+memcmp:
+	cmp	r2, #0
+	beq	zero_len_out
+	mov	r3, r0
+1:	ldrb	r0, [r3], #1
+	ldrb	r12, [r1], #1
+	subs	r0, r0, r12
+	bxne	lr
+	subs	r2, r2, #1
+	bne	1b
+	bx	lr
+
+zero_len_out:
+	mov	r0, #0
+	bx	lr
diff --git a/src/target/firmware/lib/strcmp.c b/src/target/firmware/lib/strcmp.c
new file mode 100644
index 0000000..9a7fa81
--- /dev/null
+++ b/src/target/firmware/lib/strcmp.c
@@ -0,0 +1,12 @@
+/*
+ * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
+ */
+
+strcmp(s1, s2)
+	register char *s1, *s2;
+{
+	while (*s1 == *s2++)
+		if (*s1++=='\0')
+			return(0);
+	return(*s1 - *--s2);
+}
diff --git a/src/target/firmware/tiffs/Makefile b/src/target/firmware/tiffs/Makefile
new file mode 100644
index 0000000..6ded9e8
--- /dev/null
+++ b/src/target/firmware/tiffs/Makefile
@@ -0,0 +1,5 @@
+
+LIBRARIES+=tiffs
+LIB_tiffs_DIR=tiffs
+LIB_tiffs_SRCS=globals.c init.c readfile.c
+
diff --git a/src/target/firmware/tiffs/globals.c b/src/target/firmware/tiffs/globals.c
new file mode 100644
index 0000000..ffbba42
--- /dev/null
+++ b/src/target/firmware/tiffs/globals.c
@@ -0,0 +1,12 @@
+/* global variables for the TIFFS reader code */
+
+#include <stdint.h>
+#include "globals.h"
+
+uint32_t tiffs_base_addr;
+uint32_t tiffs_sector_size;
+unsigned tiffs_nsectors;
+
+struct tiffs_inode *tiffs_active_index;
+int tiffs_root_ino;
+int tiffs_init_done;
diff --git a/src/target/firmware/tiffs/globals.h b/src/target/firmware/tiffs/globals.h
new file mode 100644
index 0000000..7c64693
--- /dev/null
+++ b/src/target/firmware/tiffs/globals.h
@@ -0,0 +1,9 @@
+/* global variables for the TIFFS reader code - extern declarations */
+
+extern uint32_t tiffs_base_addr;
+extern uint32_t tiffs_sector_size;
+extern unsigned tiffs_nsectors;
+
+extern struct tiffs_inode *tiffs_active_index;
+extern int tiffs_root_ino;
+extern int tiffs_init_done;
diff --git a/src/target/firmware/tiffs/init.c b/src/target/firmware/tiffs/init.c
new file mode 100644
index 0000000..6a3b48a
--- /dev/null
+++ b/src/target/firmware/tiffs/init.c
@@ -0,0 +1,103 @@
+/* TIFFS (TI Flash File System) reader implementation */
+
+/*
+ * (C) 2017 by Mychaela Falconia <mychaela.falconia at gmail.com>
+ * Tweaked (coding style changes) by Vadim Yanitskiy <axilirator at gmail.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <tiffs.h>
+#include "globals.h"
+
+/* Each flash sector used for TIFFS begins with this 6-byte signature */
+static const uint8_t ffs_sector_signature[6] = {
+	'F', 'f', 's', '#', 0x10, 0x02
+};
+
+static int find_indexblk(void)
+{
+	uint32_t sector_addr;
+	uint8_t *sector_ptr;
+	unsigned i;
+
+	sector_addr = tiffs_base_addr;
+	for (i = 0; i < tiffs_nsectors; i++) {
+		sector_ptr = (uint8_t *) sector_addr;
+		if (!memcmp(sector_ptr, ffs_sector_signature, 6)
+		    && sector_ptr[8] == 0xAB) {
+			printf("Found TIFFS active index block "
+				"at 0x%" PRIx32 "\n", sector_addr);
+			tiffs_active_index = (struct tiffs_inode *) sector_addr;
+			return 0;
+		}
+		sector_addr += tiffs_sector_size;
+	}
+
+	puts("TIFFS error: no active index block found\n");
+	return -1;
+}
+
+static int find_rootino(void)
+{
+	struct tiffs_inode *irec;
+	unsigned ino = 0;
+
+	while (++ino < tiffs_sector_size >> 4) {
+		irec = tiffs_active_index + ino;
+		if (irec->type != TIFFS_OBJTYPE_DIR)
+			continue;
+		if (*INODE_TO_DATAPTR(irec) != '/')
+			continue;
+
+		printf("Found TIFFS root inode at #%x\n", ino);
+		tiffs_root_ino = ino;
+		return 0;
+	}
+
+	puts("TIFFS error: no root inode found\n");
+	return -1;
+}
+
+int tiffs_init(uint32_t base_addr, uint32_t sector_size, unsigned nsectors)
+{
+	int rc;
+
+	printf("Looking for TIFFS (TI Flash File System) header at "
+		"0x%" PRIx32 ", %u sectors of 0x%" PRIx32 " bytes\n",
+		base_addr, nsectors, sector_size);
+
+	tiffs_base_addr = base_addr;
+	tiffs_sector_size = sector_size;
+	tiffs_nsectors = nsectors;
+
+	rc = find_indexblk();
+	if (rc < 0)
+		return rc;
+	rc = find_rootino();
+	if (rc < 0)
+		return rc;
+
+	tiffs_init_done = 1;
+	return 0;
+}
diff --git a/src/target/firmware/tiffs/readfile.c b/src/target/firmware/tiffs/readfile.c
new file mode 100644
index 0000000..f3e916f
--- /dev/null
+++ b/src/target/firmware/tiffs/readfile.c
@@ -0,0 +1,264 @@
+/* TIFFS (TI Flash File System) reader implementation */
+
+/*
+ * (C) 2017 by Mychaela Falconia <mychaela.falconia at gmail.com>
+ * Tweaked (coding style changes) by Vadim Yanitskiy <axilirator at gmail.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <tiffs.h>
+#include "globals.h"
+
+extern char *index();
+
+#define	MAX_FN_COMPONENT	20
+
+static unsigned find_named_child(unsigned start, const char *seekname)
+{
+	struct tiffs_inode *irec;
+	unsigned ino;
+
+	for (ino = start; ino != 0xFFFF; ino = irec->sibling) {
+		irec = tiffs_active_index + ino;
+		if (!irec->type)
+			continue;
+		if (!strcmp((const char *) INODE_TO_DATAPTR(irec), seekname))
+			return ino;
+	}
+
+	return 0;
+}
+
+static int pathname_to_inode(const char *pathname)
+{
+	char seekname[MAX_FN_COMPONENT + 1];
+	struct tiffs_inode *irec;
+	const char *cur, *next;
+	unsigned ino, namelen;
+
+	cur = pathname;
+	if (*cur == '/')
+		cur++;
+
+	for (ino = tiffs_root_ino; cur; cur = next) {
+		if (!*cur)
+			break;
+
+		next = index(cur, '/');
+		if (next == cur) {
+			puts("Malformed TIFFS pathname: multiple adjacent slashes\n");
+			return -1;
+		} else if (next) {
+			namelen = next - cur;
+			next++;
+		} else {
+			namelen = strlen(cur);
+		}
+
+		if (namelen > MAX_FN_COMPONENT) {
+			puts("Malformed TIFFS pathname: component name too long\n");
+			return -1;
+		}
+
+		memcpy(seekname, cur, namelen);
+		seekname[namelen] = '\0';
+
+		irec = tiffs_active_index + ino;
+		if (irec->type != TIFFS_OBJTYPE_DIR) {
+			/* printf("Error: non-terminal non-directory\n"); */
+			return 0;
+		}
+		ino = find_named_child(irec->descend, seekname);
+		if (!ino) {
+			/* printf("Error: pathname component not found\n"); */
+			return 0;
+		}
+	}
+
+	return ino;
+}
+
+static uint8_t *find_endofchunk(int ino)
+{
+	struct tiffs_inode *irec;
+	uint8_t *ptr;
+	int i;
+
+	irec = tiffs_active_index + ino;
+	ptr = INODE_TO_DATAPTR(irec) + irec->len;
+
+	for (i = 0; i < 16; i++) {
+		ptr--;
+		if (!*ptr)
+			return ptr;
+		if (*ptr != 0xFF)
+			break;
+	}
+
+	printf("TIFFS error: inode #%x has no valid termination\n", ino);
+	return ptr; /* XXX */
+}
+
+static int get_file_head(const char *pathname, uint8_t **startret,
+			 size_t *sizeret, int *continue_ret)
+{
+	struct tiffs_inode *irec;
+	uint8_t *start, *end;
+	int ino, cont, size;
+
+	ino = pathname_to_inode(pathname);
+	if (ino <= 0)
+		return ino;
+
+	irec = tiffs_active_index + ino;
+	if (irec->type != TIFFS_OBJTYPE_FILE) {
+		printf("TIFFS error: '%s' is not a regular file\n", pathname);
+		return -1;
+	}
+
+	start = INODE_TO_DATAPTR(irec);
+	start += strlen((const char *) 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 1;
+}
+
+static int get_segment(int ino, uint8_t **startret,
+		       size_t *sizeret, int *continue_ret)
+{
+	struct tiffs_inode *irec;
+	uint8_t *start, *end;
+	int cont, size;
+
+	for (;;) {
+		irec = tiffs_active_index + ino;
+		if (irec->type)
+			break;
+		if (irec->sibling == 0xFFFF) {
+			printf("TIFFS error: segment inode #%d: "
+				"deleted and no sibling\n", ino);
+			return -1;
+		}
+		ino = irec->sibling;
+	}
+
+	if (irec->type != TIFFS_OBJTYPE_SEGMENT) {
+		printf("TIFFS 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("TIFFS error: segment inode #%x has 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;
+}
+
+int tiffs_read_file_maxlen(const char *pathname, uint8_t *buf,
+			   size_t maxlen, size_t *lenrtn)
+{
+	size_t chunk_size, real_len, roomleft;
+	uint8_t *chunk_start;
+	int stat, cont;
+
+	if (!tiffs_init_done) {
+		puts("TIFFS reader is not initialized\n");
+		return -1;
+	}
+
+	stat = get_file_head(pathname, &chunk_start, &chunk_size, &cont);
+	if (stat <= 0)
+		return stat;
+	if (chunk_size > maxlen) {
+toobig:		printf("TIFFS error: '%s' is bigger than the read buffer\n", pathname);
+		return -1;
+	}
+
+	real_len = chunk_size;
+	memcpy(buf, chunk_start, chunk_size);
+	buf += chunk_size;
+	roomleft = maxlen - chunk_size;
+	while (cont) {
+		stat = get_segment(cont, &chunk_start, &chunk_size, &cont);
+		if (stat < 0)
+			return stat;
+		if (chunk_size > roomleft)
+			goto toobig;
+
+		real_len += chunk_size;
+		memcpy(buf, chunk_start, chunk_size);
+		buf += chunk_size;
+		roomleft -= chunk_size;
+	}
+
+	if (lenrtn)
+		*lenrtn = real_len;
+
+	return 1;
+}
+
+int tiffs_read_file_fixedlen(const char *pathname, uint8_t *buf,
+			     size_t expect_len)
+{
+	size_t real_len;
+	int rc;
+
+	rc = tiffs_read_file_maxlen(pathname, buf, expect_len, &real_len);
+	if (rc <= 0)
+		return rc;
+	if (real_len != expect_len) {
+		printf("TIFFS error: '%s' has the wrong length\n", pathname);
+		return -1;
+	}
+
+	return 1;
+}

-- 
To view, visit https://gerrit.osmocom.org/12885
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: If6e212baeb10953129fb0d5253d263567f5e12d6
Gerrit-Change-Number: 12885
Gerrit-PatchSet: 4
Gerrit-Owner: Vadim Yanitskiy <axilirator at gmail.com>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder (1000002)
Gerrit-Reviewer: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Vadim Yanitskiy <axilirator at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190220/97ee5685/attachment.htm>


More information about the gerrit-log mailing list