summaryrefslogtreecommitdiff
path: root/nftldump.c
diff options
context:
space:
mode:
Diffstat (limited to 'nftldump.c')
-rw-r--r--nftldump.c278
1 files changed, 0 insertions, 278 deletions
diff --git a/nftldump.c b/nftldump.c
deleted file mode 100644
index 32f4f2f..0000000
--- a/nftldump.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * nftldump.c: Dumping the content of NFTL partitions on a "Physical Disk"
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * ToDo:
- * 1. UnitSizeFactor != 0xFF cases
- * 2. test, test, and test !!!
- */
-
-#define PROGRAM_NAME "nftldump"
-
-#define _XOPEN_SOURCE 500 /* For pread */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include <sys/ioctl.h>
-#include <asm/types.h>
-#include <mtd/mtd-user.h>
-#include <mtd/nftl-user.h>
-#include <mtd_swab.h>
-
-static struct NFTLMediaHeader MedHead[2];
-static mtd_info_t meminfo;
-
-static struct nftl_oob oobbuf;
-static struct mtd_oob_buf oob = {0, 16, (unsigned char *)&oobbuf};
-
-static int fd, ofd = -1;;
-static int NumMedHeads;
-
-static unsigned char BadUnitTable[MAX_ERASE_ZONES];
-
-#define SWAP16(x) do { x = le16_to_cpu(x); } while(0)
-#define SWAP32(x) do { x = le32_to_cpu(x); } while(0)
-
-/* VUCtable, store the Erase Unit Number of the first Erase Unit in the chain */
-static unsigned short *VUCtable;
-
-/* FixMe: make this dynamic allocated */
-#define ERASESIZE 0x2000
-#define NUMVUNITS ((40*1024*1024) / ERASESIZE)
-static union nftl_uci UCItable[NUMVUNITS][3];
-
-static unsigned short nextEUN(unsigned short curEUN)
-{
- return UCItable[curEUN][0].a.ReplUnitNum;
-}
-
-static unsigned int find_media_headers(void)
-{
- int i;
- static unsigned long ofs = 0;
-
- NumMedHeads = 0;
- while (ofs < meminfo.size) {
- pread(fd, &MedHead[NumMedHeads], sizeof(struct NFTLMediaHeader), ofs);
- if (!strncmp(MedHead[NumMedHeads].DataOrgID, "ANAND", 6)) {
- SWAP16(MedHead[NumMedHeads].NumEraseUnits);
- SWAP16(MedHead[NumMedHeads].FirstPhysicalEUN);
- SWAP32(MedHead[NumMedHeads].FormattedSize);
-
- if (NumMedHeads == 0) {
- printf("NFTL Media Header found at offset 0x%08lx:\n", ofs);
- printf("NumEraseUnits: %d\n",
- MedHead[NumMedHeads].NumEraseUnits);
- printf("FirstPhysicalEUN: %d\n",
- MedHead[NumMedHeads].FirstPhysicalEUN);
- printf("Formatted Size: %d\n",
- MedHead[NumMedHeads].FormattedSize);
- printf("UnitSizeFactor: 0x%x\n",
- MedHead[NumMedHeads].UnitSizeFactor);
-
- /* read BadUnitTable, I don't know why pread() does not work for
- larger (7680 bytes) chunks */
- for (i = 0; i < MAX_ERASE_ZONES; i += 512)
- pread(fd, &BadUnitTable[i], 512, ofs + 512 + i);
- } else
- printf("Second NFTL Media Header found at offset 0x%08lx\n",ofs);
- NumMedHeads++;
- }
-
- ofs += meminfo.erasesize;
- if (NumMedHeads == 2) {
- if (strncmp((char *)&MedHead[0], (char *)&MedHead[1], sizeof(struct NFTLMediaHeader)) != 0) {
- printf("warning: NFTL Media Header is not consistent with "
- "Spare NFTL Media Header\n");
- }
- break;
- }
- }
-
- /* allocate Virtual Unit Chain table for this NFTL partition */
- VUCtable = calloc(MedHead[0].NumEraseUnits, sizeof(unsigned short));
- return NumMedHeads;
-}
-
-static void dump_erase_units(void)
-{
- int i, j;
- unsigned long ofs;
-
- for (i = MedHead[0].FirstPhysicalEUN; i < MedHead[0].FirstPhysicalEUN +
- MedHead[0].NumEraseUnits; i++) {
- /* For each Erase Unit */
- ofs = i * meminfo.erasesize;
-
- /* read the Unit Control Information */
- for (j = 0; j < 3; j++) {
- oob.start = ofs + (j * 512);
- if (ioctl(fd, MEMREADOOB, &oob))
- printf("MEMREADOOB at %lx: %s\n",
- (unsigned long) oob.start, strerror(errno));
- memcpy(&UCItable[i][j], &oobbuf.u, 8);
- }
- if (UCItable[i][1].b.EraseMark != cpu_to_le16(0x3c69)) {
- printf("EraseMark not present in unit %d: %x\n",
- i, UCItable[i][1].b.EraseMark);
- } else {
- /* a properly formatted unit */
- SWAP16(UCItable[i][0].a.VirtUnitNum);
- SWAP16(UCItable[i][0].a.ReplUnitNum);
- SWAP16(UCItable[i][0].a.SpareVirtUnitNum);
- SWAP16(UCItable[i][0].a.SpareReplUnitNum);
- SWAP32(UCItable[i][1].b.WearInfo);
- SWAP16(UCItable[i][1].b.EraseMark);
- SWAP16(UCItable[i][1].b.EraseMark1);
- SWAP16(UCItable[i][2].c.FoldMark);
- SWAP16(UCItable[i][2].c.FoldMark1);
-
- if (!(UCItable[i][0].a.VirtUnitNum & 0x8000)) {
- /* If this is the first in a chain, store the EUN in the VUC table */
- if (VUCtable[UCItable[i][0].a.VirtUnitNum & 0x7fff]) {
- printf("Duplicate start of chain for VUC %d: "
- "Unit %d replaces Unit %d\n",
- UCItable[i][0].a.VirtUnitNum & 0x7fff,
- i, VUCtable[UCItable[i][0].a.VirtUnitNum & 0x7fff]);
- }
- VUCtable[UCItable[i][0].a.VirtUnitNum & 0x7fff] = i;
- }
- }
-
- switch (BadUnitTable[i]) {
- case ZONE_BAD_ORIGINAL:
- printf("Unit %d is marked as ZONE_BAD_ORIGINAL\n", i);
- continue;
- case ZONE_BAD_MARKED:
- printf("Unit %d is marked as ZONE_BAD_MARKED\n", i);
- continue;
- }
-
- /* ZONE_GOOD */
- if (UCItable[i][0].a.VirtUnitNum == 0xffff)
- printf("Unit %d is free\n", i);
- else
- printf("Unit %d is in chain %d and %s a replacement\n", i,
- UCItable[i][0].a.VirtUnitNum & 0x7fff,
- UCItable[i][0].a.VirtUnitNum & 0x8000 ? "is" : "is not");
- }
-}
-
-static void dump_virtual_units(void)
-{
- int i, j;
- char readbuf[512];
-
- for (i = 0; i < (MedHead[0].FormattedSize / meminfo.erasesize); i++) {
- unsigned short curEUN = VUCtable[i];
-
- printf("Virtual Unit #%d: ", i);
- if (!curEUN) {
- printf("Not present\n");
- continue;
- }
- printf("%d", curEUN);
-
- /* walk through the Virtual Unit Chain */
- while ((curEUN = nextEUN(curEUN)) != 0xffff) {
- printf(", %d", curEUN & 0x7fff);
- }
- printf("\n");
-
- if (ofd != -1) {
- /* Actually write out the data */
- for (j = 0; j < meminfo.erasesize / 512; j++) {
- /* For each sector in the block */
- unsigned short lastgoodEUN = 0xffff, thisEUN = VUCtable[i];
- unsigned int status;
-
- if (thisEUN == 0xffff) thisEUN = 0;
-
- while (thisEUN && (thisEUN & 0x7fff) != 0x7fff) {
- oob.start = (thisEUN * ERASESIZE) + (j * 512);
- ioctl(fd, MEMREADOOB, &oob);
- status = oobbuf.b.Status | oobbuf.b.Status1;
-
- switch (status) {
- case SECTOR_FREE:
- /* This is still free. Don't look any more */
- thisEUN = 0;
- break;
-
- case SECTOR_USED:
- /* SECTOR_USED. This is a good one. */
- lastgoodEUN = thisEUN;
- break;
- }
-
- /* Find the next erase unit in this chain, if any */
- if (thisEUN)
- thisEUN = nextEUN(thisEUN) & 0x7fff;
- }
-
- if (lastgoodEUN == 0xffff)
- memset(readbuf, 0, 512);
- else
- pread(fd, readbuf, 512,
- (lastgoodEUN * ERASESIZE) + (j * 512));
-
- write(ofd, readbuf, 512);
- }
-
- }
- }
-}
-
-int main(int argc, char **argv)
-{
- if (argc < 2) {
- printf("Usage: %s <device> [<outfile>]\n", PROGRAM_NAME);
- exit(1);
- }
- fd = open(argv[1], O_RDONLY);
- if (fd == -1) {
- perror("open flash");
- exit (1);
- }
-
- if (argc > 2) {
- ofd = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT, 0644);
- if (ofd == -1)
- perror ("open outfile");
- }
-
- /* get size information of the MTD device */
- if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
- perror("ioctl(MEMGETINFO)");
- close(fd);
- return 1;
- }
-
- while (find_media_headers() != 0) {
- dump_erase_units();
- dump_virtual_units();
- free(VUCtable);
- }
-
- exit(0);
-}