lsflash.c 3.22 KB
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>

#include <PR/bbfs.h>
#include "ecc256.h"
#include "flashif.h"

#define MAX_FSFILES	64

static int blocks;

static int verbose;

static BbFat16 fat;
flashif_t* fif;

static int
read_fat(flashif_t *fif, BbFat16* fat) {
    BbFat16 tfat[BB_FAT16_BLOCKS];
    int i, start = (*fif->blocks)(fif->f)-1, count = 0, bad = 0, best = 0;
    int j, which = -1, list[BB_FAT16_BLOCKS];
    while (count+bad < BB_FAT16_BLOCKS) {
	if ((*fif->read_block)(fif->f, start, &tfat[count], 0, YES_ECC) == 0) {
	    list[count] = start;
	    count++;
	} else
	    bad++;
	start--;
    }
    if (!count) return -1;
    /* got at least one good block */
    for(i = 0; i < count; i++) {
	u16 csum = 0, *p = (u16*)&tfat[i];
	for(j = 0; j < BB_FL_BLOCK_SIZE/sizeof(u16); j++)
	    csum += ntohs(p[j]);
	if (csum != BB_FAT16_CKSUM) {
	    if (verbose > 1) printf("bad csum %d %x\n", i, csum);
	} else if (ntohl(tfat[i].seq) > best) {
	    which = i;
	    best = ntohl(tfat[i].seq);
	}
    }
    if (which == -1) return -1;
    if (verbose) printf("fat block %d(%d)\n", which, list[which]);
    /* fix endianness */
    memcpy(fat, &tfat[which], sizeof *fat);
    for(i = 0; i < BB_FAT16_ENTRIES; i++)
	fat->entry[i] = ntohs(fat->entry[i]);
    for(i = 0; i < BB_INODE16_ENTRIES; i++) {
	fat->inode[i].block = ntohs(fat->inode[i].block);
	fat->inode[i].size = ntohl(fat->inode[i].size);
    }
    fat->seq = ntohl(fat->seq);
    fat->cksum = ntohs(fat->cksum);
    return 0;
}

int
main(int argc, char* argv[]) {
    int c, i;

    while ((c = getopt(argc, argv, "b:k:l:s:v")) != EOF) {
        switch(c) {
	case 'v':
	    verbose++; break;
	case '?':
	    fprintf(stderr, "Usage: lsflash [-v] [device]\n");
	    return 1;
	}
    }

    if (!(fif = new_fileif()))
	return 1;
    if (!(*fif->open)(&fif->f, optind < argc ? argv[optind] : "flash.img", 1,
                      FLASHIF_DEFAULT_NUM_BLKS)) {
	fprintf(stderr, "flash device open failed\n");
	return 1;
    }
    blocks = (*fif->blocks)(fif->f);

    if (read_fat(fif, &fat) < 0) {
	fprintf(stderr, "corrupt or no file system\n");
	return 1;
    }

    for(i = 0; i < BB_INODE16_ENTRIES; i++) {
	if (fat.inode[i].type) {
	    printf("%8.8s.%-3.3s %2d %8ld%s", fat.inode[i].name, fat.inode[i].name+8, i, fat.inode[i].size, verbose ? "  " : "\n");
	    if (verbose) {
		int j;
		for(j = fat.inode[i].block; j != BB_FAT_LAST; j = fat.entry[j])
		    printf("%4d ", j);
		printf("\n");
	    }
	}
    }

    if (verbose) {
	int free = 0, bad = 0, rsv = 0;
	for(i = 0; i < blocks; i++) {
	    if (fat.entry[i] == BB_FAT_AVAIL) free++;
	    else if (fat.entry[i] == BB_FAT_BAD) bad++;
	    else if (fat.entry[i] == BB_FAT_RESERVED) rsv++;
	}
	printf("free blocks %d %.2f MB\n", free, BB_FL_BLOCK_TO_BYTE(free)/(1024.*1024.));
	printf("reserved blocks %d %.1f%%\n", rsv, 100.f*rsv/blocks);
	printf("bad blocks %d %.1f%%\n", bad, 100.f*bad/blocks);
	if (verbose > 1) {
	    for(i = 0; i < BB_FAT16_ENTRIES; i++) {
		int t = fat.entry[i];
		printf("%c", t == BB_FAT_AVAIL ? '.' : t == BB_FAT_BAD ? '@' : t == BB_FAT_RESERVED ? '/' : '|');
		if ((i & 63) == 63) printf("\n");
	    }
	}
    }
    (*fif->close)(fif->f);
    return 0;
}