diff mpffs/common.c @ 30:9c3c5a572b57

mpffs-ls works with the length code stubbed out
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 30 Jun 2013 06:28:58 +0000
parents e96d6862cec0
children 3cca8070ef0f
line wrap: on
line diff
--- a/mpffs/common.c	Sun Jun 30 05:16:23 2013 +0000
+++ b/mpffs/common.c	Sun Jun 30 06:28:58 2013 +0000
@@ -17,13 +17,16 @@
 #include "struct.h"
 
 u8 mpffs_header[6] = {'F', 'f', 's', '#', 0x10, 0x02};
+u8 blank_flash_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+			   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 
 char *imgfile;
 u32 eraseblk_size;
 int total_blocks;
 u32 total_ffs_size;
 u8 *image, *indexblk;
-int index_blk_num, root_node_no;
+int index_blk_num = -1, root_node_no;
+struct objinfo root;
 int verbose;
 
 /*
@@ -42,13 +45,58 @@
 
 eraseblk_size_reasonable()
 {
-	if (count_ones(eraseblk_size) != 1 || eraseblk_size < 16384) {
+	if (count_ones(eraseblk_size) != 1 || eraseblk_size < 16384 ||
+	    eraseblk_size > 0x100000) {
 		fprintf(stderr, "0x%lx is an unreasonable erase block size\n",
 			(u_long) eraseblk_size);
 		exit(1);
 	}
 }
 
+parse_cmdline_options(argc, argv)
+	char **argv;
+{
+	extern char *optarg;
+	int c;
+
+	while ((c = getopt(argc, argv, "a:e:mn:pr:v")) != EOF)
+		switch (c) {
+		case 'a':
+			index_blk_num = atoi(optarg);
+			continue;
+		case 'e':
+			eraseblk_size = strtoul(optarg, 0, 0);
+			eraseblk_size_reasonable();
+			continue;
+		case 'm':	/* "moko" */
+			eraseblk_size = 0x10000;
+			total_blocks = 7;
+			continue;
+		case 'n':
+			total_blocks = atoi(optarg);
+			if (total_blocks < 1) {
+				fprintf(stderr, "invalid -n value\n");
+				exit(1);
+			}
+			continue;
+		case 'p':	/* Pirelli */
+			eraseblk_size = 0x40000;
+			total_blocks = 18;
+			continue;
+		case 'r':
+			root_node_no = atoi(optarg);
+			continue;
+		case 'v':
+			verbose++;
+			continue;
+		default:
+			usage();
+			exit(1);
+		}
+
+	return(0);
+}
+
 read_img_file()
 {
 	int fd;
@@ -114,8 +162,8 @@
 	int i, abcnt;
 	u8 *ptr;
 
-	if (index_blk_num) {
-		if (index_blk_num < 0 || index_blk_num >= total_blocks) {
+	if (index_blk_num >= 0) {
+		if (index_blk_num >= total_blocks) {
 			fprintf(stderr,
 				"invalid block # given with the -a option\n");
 			exit(1);
@@ -205,7 +253,7 @@
 		exit(1);
 	}
 	dptr <<= 4;
-	if (dptr >= total_img_size - oi->len)
+	if (dptr > total_ffs_size - oi->len)
 		goto invdptr;
 	oi->offset = dptr;
 	oi->dataptr = image + dptr;
@@ -262,3 +310,64 @@
 		ch->offset, ch->entryno);
 	exit(1);
 }
+
+find_root_node()
+{
+	struct objinfo obj;
+	u16 lim;
+
+	lim = (eraseblk_size >> 4) - 1;
+	if (root_node_no) {
+		if (root_node_no < 1 || root_node_no > lim) {
+			fprintf(stderr,
+				"root node # given with -r is invalid\n");
+			exit(1);
+		}
+		return(1);
+	}
+	for (obj.entryno = 1; obj.entryno <= lim; obj.entryno++) {
+		get_index_entry(&obj);
+		if (!bcmp(obj.idxrec, blank_flash_line, 16))
+			break;
+		if (obj.type != 0xF2)
+			continue;
+		validate_chunk(&obj);
+		validate_obj_name(&obj);
+		if (*obj.dataptr != '/')
+			continue;
+		root_node_no = obj.entryno;
+		if (verbose)
+			printf("Found root node at index #%x\n", root_node_no);
+		return(0);
+	}
+	fprintf(stderr, "error: no root node found (try -r)\n");
+	exit(1);
+}
+
+validate_root_node()
+{
+	root.entryno = root_node_no;
+	get_index_entry(&root);
+	validate_chunk(&root);
+	validate_obj_name(&root);
+	if (verbose)
+		printf("Root node name: %s\n", (char *)root.dataptr);
+	if (root.type != 0xF2) {
+		fprintf(stderr,
+	"error: index entry #%x (expected root dir) is not a directory\n",
+			root_node_no);
+		exit(1);
+	}
+	if (root.sibling != 0xFFFF)
+		fprintf(stderr,
+			"warning: root entry has a non-nil sibling pointer\n");
+	return(0);
+}
+
+preliminaries()
+{
+	read_img_file();
+	find_index_block();
+	find_root_node();
+	validate_root_node();
+}