diff options
-rw-r--r-- | src/target/firmware/Makefile | 2 | ||||
-rw-r--r-- | src/target/firmware/board/compal_e86/init.c | 4 | ||||
-rwxr-xr-x | src/target/firmware/board/compal_e88/init.c | 4 | ||||
-rw-r--r-- | src/target/firmware/board/fcdev3b/init.c | 4 | ||||
-rw-r--r-- | src/target/firmware/board/gta0x/init.c | 4 | ||||
-rw-r--r-- | src/target/firmware/board/pirelli_dpl10/init.c | 4 | ||||
-rw-r--r-- | src/target/firmware/include/string.h | 3 | ||||
-rw-r--r-- | src/target/firmware/include/tiffs.h | 33 | ||||
-rw-r--r-- | src/target/firmware/lib/Makefile | 5 | ||||
-rw-r--r-- | src/target/firmware/lib/index.c | 12 | ||||
-rw-r--r-- | src/target/firmware/lib/memcmp.S | 18 | ||||
-rw-r--r-- | src/target/firmware/lib/strcmp.c | 12 | ||||
-rw-r--r-- | src/target/firmware/tiffs/Makefile | 5 | ||||
-rw-r--r-- | src/target/firmware/tiffs/globals.c | 12 | ||||
-rw-r--r-- | src/target/firmware/tiffs/globals.h | 9 | ||||
-rw-r--r-- | src/target/firmware/tiffs/init.c | 103 | ||||
-rw-r--r-- | src/target/firmware/tiffs/readfile.c | 264 |
17 files changed, 496 insertions, 2 deletions
diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile index 1196d10f..914db6c7 100644 --- a/src/target/firmware/Makefile +++ b/src/target/firmware/Makefile @@ -107,6 +107,7 @@ ANY_APP_LIBS+= calypso/libcalypso.a \ 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 @@ INCLUDES=-Iinclude/ -I../../../include -I../../shared/libosmocore/include -I../. -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 fed9f85a..725f1841 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 @@ void board_init(int with_irq) /* 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 04ae4588..956f7dc5 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 @@ void board_init(int with_irq) /* 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 92be6674..c0705364 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 @@ void board_init(int with_irq) /* 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 b93f79c7..7fba7561 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 @@ void board_init(int with_irq) /* 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 da233088..1af6e7c9 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 @@ void board_init(int with_irq) /* 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 f060659a..ecef13d0 100644 --- a/src/target/firmware/include/string.h +++ b/src/target/firmware/include/string.h @@ -9,4 +9,7 @@ size_t strlen(const char *s); 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 00000000..4713c4e1 --- /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 a2a6d457..75461984 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 00000000..bb304c04 --- /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 00000000..c60b170b --- /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 00000000..9a7fa818 --- /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 00000000..6ded9e87 --- /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 00000000..ffbba42a --- /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 00000000..7c64693b --- /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 00000000..6a3b48a4 --- /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@gmail.com> + * Tweaked (coding style changes) by Vadim Yanitskiy <axilirator@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 00000000..f3e916fa --- /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@gmail.com> + * Tweaked (coding style changes) by Vadim Yanitskiy <axilirator@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; +} |