FreeCalypso > hg > freecalypso-tools
changeset 705:12ae93940467
tiffs-mkfs program written, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 20 May 2020 06:55:58 +0000 |
parents | dacd9fdc392a |
children | 850bf712c1fc |
files | .hgignore ffstools/tiffs-mkfs/Makefile ffstools/tiffs-mkfs/ffsparam.c ffstools/tiffs-mkfs/globals.c ffstools/tiffs-mkfs/globals.h ffstools/tiffs-mkfs/input.c ffstools/tiffs-mkfs/main.c ffstools/tiffs-mkfs/output.c ffstools/tiffs-mkfs/struct.h |
diffstat | 9 files changed, 592 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Thu May 07 03:39:55 2020 +0000 +++ b/.hgignore Wed May 20 06:55:58 2020 +0000 @@ -15,6 +15,7 @@ ^ffstools/tiaud/compile$ ^ffstools/tiaud/decomp$ ^ffstools/tiaud/mkvol$ +^ffstools/tiffs-mkfs/tiffs-mkfs$ ^ffstools/tiffs-rd/tiffs$ ^ffstools/tiffs-wrappers/mokoffs$ ^ffstools/tiffs-wrappers/pirffs$
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-mkfs/Makefile Wed May 20 06:55:58 2020 +0000 @@ -0,0 +1,23 @@ +CC= gcc +CFLAGS= -O2 +PROG= tiffs-mkfs +OBJS= ffsparam.o globals.o input.o main.o output.o +HDRS= globals.h struct.h + +INSTALL_PREFIX= /opt/freecalypso + +INSTBIN=${INSTALL_PREFIX}/bin + +all: ${PROG} + +${PROG}: ${OBJS} + ${CC} -o $@ ${OBJS} + +${OBJS}: ${HDRS} + +install: ${PROG} + mkdir -p ${INSTBIN} + install -c ${PROG} ${INSTBIN} + +clean: + rm -f ${PROG} *.o *.out *errs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-mkfs/ffsparam.c Wed May 20 06:55:58 2020 +0000 @@ -0,0 +1,84 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <ctype.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "struct.h" +#include "globals.h" + +void +parse_org_arg(arg) + char *arg; +{ + char *cp; + + cp = index(arg, 'x'); + if (!cp || !isdigit(cp[1]) || !isdigit(arg[0])) { + fprintf(stderr, + "error: TIFFS organization argument \"%s\" is invalid\n", arg); + exit(1); + } + *cp++ = '\0'; + if (!strcmp(arg, "8")) + ffs_sector_size = 0x2000; + else if (!strcmp(arg, "16")) + ffs_sector_size = 0x4000; + else if (!strcmp(arg, "32")) + ffs_sector_size = 0x8000; + else if (!strcmp(arg, "64")) + ffs_sector_size = 0x10000; + else if (!strcmp(arg, "128")) + ffs_sector_size = 0x20000; + else if (!strcmp(arg, "256")) + ffs_sector_size = 0x40000; + else { + fprintf(stderr, + "error: \"%s\" is not a recognized flash sector size\n", + arg); + exit(1); + } + ffs_nsectors = atoi(cp); + if (ffs_nsectors < 3 || ffs_nsectors > 128) { + fprintf(stderr, + "error: \"%s\" is not a reasonable number of FFS sectors\n", + cp); + exit(1); + } +} + +void +preen_chunk_size_max() +{ + if (chunk_size_max) { + if (chunk_size_max > ffs_sector_size / 2) { + fprintf(stderr, + "error: max chunk size specified with -c is too large\n"); + exit(1); + } + return; + } + /* default matching TI's code */ + if (ffs_sector_size * ffs_nsectors > 1024*1024) + chunk_size_max = 8192; + else if (ffs_sector_size / 8 < 2048) + chunk_size_max = ffs_sector_size / 8; + else + chunk_size_max = 2048; +} + +void +preen_block_files_max() +{ + unsigned journal_size; + + if (block_files_max) + return; + /* default matching TI's code */ + journal_size = ffs_sector_size >> 4; + if (journal_size < 1024) + journal_size = 1024; + block_files_max = (journal_size >> 4) - 6; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-mkfs/globals.c Wed May 20 06:55:58 2020 +0000 @@ -0,0 +1,22 @@ +/* + * Definitions of global variables for the tiffs-mkfs program. + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <stdint.h> +#include "struct.h" + +unsigned ffs_sector_size, ffs_nsectors; +char *format_name; +unsigned chunk_size_max, block_files_max; +u_char *inode_block, *data_block; +struct tiffs_inode *inode_array; +unsigned inode_fill_level, data_fill_level, objects_in_block; +unsigned blocks_written; + +char *input_host_dir; +struct tree_object root; + +char *output_filename; +int output_fd;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-mkfs/globals.h Wed May 20 06:55:58 2020 +0000 @@ -0,0 +1,18 @@ +/* + * extern declarations of global variables + */ + +extern unsigned ffs_sector_size, ffs_nsectors; +extern unsigned ffs_nsectors; +extern char *format_name; +extern unsigned chunk_size_max, block_files_max; +extern u_char *inode_block, *data_block; +extern struct tiffs_inode *inode_array; +extern unsigned inode_fill_level, data_fill_level, objects_in_block; +extern unsigned blocks_written; + +extern char *input_host_dir; +extern struct tree_object root; + +extern char *output_filename; +extern int output_fd;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-mkfs/input.c Wed May 20 06:55:58 2020 +0000 @@ -0,0 +1,112 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <dirent.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include "struct.h" +#include "globals.h" + +void +read_dir_level(dto, srcpath, depth) + struct tree_object *dto; + char *srcpath; +{ + DIR *rdd; + struct dirent *dirent; + char hostpath_child[MAXPATHLEN]; + struct stat hst; + struct tree_object *cto; + unsigned nchildren; + + dto->is_dir = 1; + rdd = opendir(srcpath); + if (!rdd) { + perror(srcpath); + exit(1); + } + nchildren = 0; + while (dirent = readdir(rdd)) { + if (dirent->d_name[0] == '.') + continue; + if (strlen(dirent->d_name) > MAX_FN_COMPONENT) { + fprintf(stderr, + "error: \"%s\" in %s exceeds the FFS component name limit\n", + dirent->d_name, srcpath); + exit(1); + } + if (nchildren >= MAX_DIR_ENTRIES) { + fprintf(stderr, "error: %s has too many children\n", + srcpath); + exit(1); + } + cto = malloc(sizeof(struct tree_object)); + if (!cto) { + perror("malloc of struct tree_object"); + exit(1); + } + strcpy(cto->name, dirent->d_name); + dto->u.d.children[nchildren++] = cto; + if (strlen(srcpath) + strlen(dirent->d_name) + 2 > + sizeof hostpath_child) { + fprintf(stderr, + "error: host side pathname buffer overflow\n"); + exit(1); + } + sprintf(hostpath_child, "%s/%s", srcpath, dirent->d_name); + if (lstat(hostpath_child, &hst) < 0) { + perror(hostpath_child); + exit(1); + } + switch (hst.st_mode & S_IFMT) { + case S_IFREG: + cto->is_dir = 0; + strcpy(cto->u.f.host_pathname, hostpath_child); + break; + case S_IFDIR: + if (depth >= MAX_DIR_NEST-1) { + fprintf(stderr, + "error: directory nesting too deep at %s\n", + hostpath_child); + exit(1); + } + read_dir_level(cto, hostpath_child, depth + 1); + break; + default: + fprintf(stderr, + "error: %s is neither a regular file nor a directory\n", + hostpath_child); + exit(1); + } + } + closedir(rdd); + dto->u.d.nchildren = nchildren; +} + +static int +compare_func(p1, p2) + struct tree_object **p1, **p2; +{ + return strcmp((*p1)->name, (*p2)->name); +} + +void +sort_dir_level(dto) + struct tree_object *dto; +{ + unsigned n; + struct tree_object *cto; + + if (dto->u.d.nchildren > 1) + qsort(dto->u.d.children, dto->u.d.nchildren, + sizeof(struct tree_object *), compare_func); + for (n = 0; n < dto->u.d.nchildren; n++) { + cto = dto->u.d.children[n]; + if (cto->is_dir) + sort_dir_level(cto); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-mkfs/main.c Wed May 20 06:55:58 2020 +0000 @@ -0,0 +1,67 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "struct.h" +#include "globals.h" + +void +process_cmdline(argc, argv) + char **argv; +{ + extern int optind; + extern char *optarg; + int c; + + while ((c = getopt(argc, argv, "c:f:m:")) != EOF) + switch (c) { + case 'c': + chunk_size_max = strtoul(optarg, 0, 0); + continue; + case 'f': + if (*optarg != '/') { + fprintf(stderr, + "error: format name must begin with \'/\'\n"); + exit(1); + } + format_name = optarg; + continue; + case 'm': + block_files_max = strtoul(optarg, 0, 0); + continue; + default: +usage: fprintf(stderr, + "usage: %s [options] <org> <srcdir> <outfile>\n", + argv[0]); + exit(1); + } + if (argc - optind != 3) + goto usage; + parse_org_arg(argv[optind]); + input_host_dir = argv[optind+1]; + output_filename = argv[optind+2]; +} + +main(argc, argv) + char **argv; +{ + process_cmdline(argc, argv); + if (!format_name) + format_name = "/"; + preen_chunk_size_max(); + preen_block_files_max(); + /* input phase */ + read_dir_level(&root, input_host_dir, 0); + sort_dir_level(&root); + /* output phase */ + prepare_output_buffers(); + open_output_file(); + create_root_dir(); + process_dir_level(&root); + finish_output(); + close(output_fd); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-mkfs/output.c Wed May 20 06:55:58 2020 +0000 @@ -0,0 +1,227 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#include <stdio.h> +#include <stdint.h> +#include <endian.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include "struct.h" +#include "globals.h" + +u_char tiffs_header[6] = {'F', 'f', 's', '#', 0x10, 0x02}; + +void +prepare_output_buffers() +{ + inode_block = malloc(ffs_sector_size); + if (!inode_block) { + perror("malloc of inode block buffer"); + exit(1); + } + memset(inode_block, 0xFF, ffs_sector_size); + bcopy(tiffs_header, inode_block, 6); + inode_block[8] = 0xAB; + inode_array = (struct tiffs_inode *) inode_block; + inode_fill_level = 1; + + data_block = malloc(ffs_sector_size); + if (!data_block) { + perror("malloc of data block buffer"); + exit(1); + } + memset(data_block, 0xFF, ffs_sector_size); + bcopy(tiffs_header, data_block, 6); + data_block[8] = 0xBD; + data_fill_level = 0x10; + objects_in_block = 0; +} + +void +open_output_file() +{ + output_fd = open(output_filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (output_fd < 0) { + perror(output_filename); + exit(1); + } + lseek(output_fd, (off_t) ffs_sector_size, SEEK_SET); +} + +void +write_out_block(buf) + u_char *buf; +{ + if (write(output_fd, buf, ffs_sector_size) != ffs_sector_size) { + perror("write of sector bits to output file"); + exit(1); + } +} + +void +flush_data_block() +{ + write_out_block(data_block); + blocks_written++; + memset(data_block + 0x10, 0xFF, ffs_sector_size - 0x10); + data_fill_level = 0x10; + objects_in_block = 0; +} + +create_object(name, type, data, datalen) + char *name; + u_char *data; + unsigned datalen; +{ + int ino; + struct tiffs_inode *inp; + unsigned size, location; + u_char *dp; + + if (inode_fill_level >= (ffs_sector_size >> 4)) { + fprintf(stderr, "error: inode block is full\n"); + exit(1); + } + ino = inode_fill_level++; + inp = inode_array + ino; + if (name) + size = strlen(name) + 1; + else + size = 0; + if (data) + size += datalen + 1; + size = (size + 15) & ~15; + if (ffs_sector_size - data_fill_level < size || + objects_in_block >= block_files_max) + flush_data_block(); + if (blocks_written >= ffs_nsectors - 2) { + fprintf(stderr, "error: wrote max number of data blocks\n"); + exit(1); + } + location = (blocks_written + 1) * ffs_sector_size + data_fill_level; + /* write the data */ + dp = data_block + data_fill_level; + if (name) { + strcpy(dp, name); + dp += strlen(name) + 1; + } + if (data) { + bcopy(data, dp, datalen); + dp += datalen; + *dp++ = 0; + } + /* fill the inode */ + inp->size = htole16(size); + inp->type = type; + inp->location = htole32(location); + inp->sequence = htole16(ino - 1); + inp->updates = 0; + /* accounting */ + data_fill_level += size; + objects_in_block++; + return ino; +} + +void +create_root_dir() +{ + int rootino; + + rootino = create_object(format_name, OBJTYPE_DIR, (u_char *) 0, 0); + root.u.d.ffs_link_ptr = &inode_array[rootino].child; +} + +create_file_object(to) + struct tree_object *to; +{ + int fd, cc; + u_char *data; + int head, seg; + struct tiffs_inode *inp; + + fd = open(to->u.f.host_pathname, O_RDONLY); + if (fd < 0) { + perror(to->u.f.host_pathname); + exit(1); + } + data = malloc(chunk_size_max); + if (!data) { + perror("malloc of file chunk buffer"); + exit(1); + } + cc = read(fd, data, chunk_size_max); + if (cc < 0) { +read_err: perror("error reading file content"); + exit(1); + } + if (cc == 0) { + /* zero length file */ + close(fd); + free(data); + return create_object(to->name, OBJTYPE_FILE, (u_char *) 0, 0); + } + head = create_object(to->name, OBJTYPE_FILE, data, cc); + inp = inode_array + head; + for (;;) { + cc = read(fd, data, chunk_size_max); + if (cc < 0) + goto read_err; + if (cc == 0) + break; + seg = create_object((char *) 0, OBJTYPE_SEGMENT, data, cc); + inp->child = htole16(seg); + inp = inode_array + seg; + } + close(fd); + free(data); + return head; +} + +create_subdir(to) + struct tree_object *to; +{ + int ino; + + ino = create_object(to->name, OBJTYPE_DIR, (u_char *) 0, 0); + to->u.d.ffs_link_ptr = &inode_array[ino].child; + return ino; +} + +void +process_dir_level(dto) + struct tree_object *dto; +{ + unsigned n; + struct tree_object *cto; + int child_ino; + + for (n = 0; n < dto->u.d.nchildren; n++) { + cto = dto->u.d.children[n]; + if (cto->is_dir) { + child_ino = create_subdir(cto); + process_dir_level(cto); + } else + child_ino = create_file_object(cto); + *dto->u.d.ffs_link_ptr = htole16(child_ino); + dto->u.d.ffs_link_ptr = &inode_array[child_ino].sibling; + } +} + +void +finish_output() +{ + if (objects_in_block) + flush_data_block(); + while (blocks_written < ffs_nsectors - 2) { + write_out_block(data_block); + blocks_written++; + } + /* free block at the end */ + data_block[8] = 0xBF; + write_out_block(data_block); + /* write out the inode block */ + lseek(output_fd, (off_t) 0, SEEK_SET); + write_out_block(inode_block); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-mkfs/struct.h Wed May 20 06:55:58 2020 +0000 @@ -0,0 +1,38 @@ +/* some general limits */ +#define MAX_FN_COMPONENT 20 +#define MAX_DIR_NEST 6 +#define MAX_DIR_ENTRIES 128 + +/* tree of content to be written */ +struct tree_object { + char name[MAX_FN_COMPONENT+1]; + int is_dir; + union { + struct { + struct tree_object *children[MAX_DIR_ENTRIES]; + unsigned nchildren; + uint16_t *ffs_link_ptr; + } d; + struct { + char host_pathname[MAXPATHLEN]; + } f; + } u; +}; + +/* actual TIFFS on-media structure */ +struct tiffs_inode { + uint16_t size; + uint8_t reserved1; + uint8_t type; + uint16_t child; + uint16_t sibling; + uint32_t location; + uint16_t sequence; + uint16_t updates; +}; + +/* TIFFS object types */ +#define OBJTYPE_FILE 0xF1 +#define OBJTYPE_DIR 0xF2 +#define OBJTYPE_SYMLINK 0xF3 +#define OBJTYPE_SEGMENT 0xF4