Zum Inhalt springen

Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
NAND Checker
#1
Hier ein NAND Checker Programm (für die Kommandozeile / CMD)

Source Code
Code:
#include <stdio.h> #include <string.h> #define BUFF_SIZE 0x210 // Size of page buffer #define MAX_BLOCKS 0x1000 // Max number of blocks for bad and reloc block map #define XEN_BLOCKNUM 0x200 // Xenon block number page offset #define JAS_BLOCKNUM 0x201 // Jasper block number page offset #define BB_BBFLAG 0x200 // BigBlock: Bad block flag page offset #define BB_PAGES 0x100 // BigBlock: Number of ECC pages in a block #define BB_PSIZE 0x210 // BigBlock: Number of bytes in a page #define BB_BSIZE (BB_PSIZE * BB_PAGES) // BigBlock: Number of bytes in a block #define SB_BBFLAG 0x205 // SmallBlock: Bad block flag page offset #define SB_PAGES 0x020 // SmallBlock: Number of ECC pages in a block #define SB_PSIZE 0x210 // SmallBlock: Number of bytes in a page #define SB_BSIZE (SB_PSIZE * SB_PAGES) // SmallBlock: Number of bytes in a block /* Some macros to clean up the code */ #define SETBIT(map,bit) ((map)[(bit)>>3] |= 1 << ((bit) & 7)) #define GETBIT(map,bit) ((map)[(bit)>>3] >> ((bit) & 7) & 1) #define BBFLAG(bb) ((bb) ? BB_BBFLAG : SB_BBFLAG) #define PAGES(bb) ((bb) ? BB_PAGES : SB_PAGES) #define PSIZE(bb) ((bb) ? BB_PSIZE : SB_PSIZE) #define BSIZE(bb) ((bb) ? BB_BSIZE : SB_BSIZE) #define BLOCKNUM(jas) ((jas) ? JAS_BLOCKNUM: XEN_BLOCKNUM) void printUsage(const char *p) { printf("Nandcheck v0.23\n"); printf("Usage: %s [-b] <filename>\n",p); printf(" -b: Use big block mode for 256MB+ NAND flash chips\n"); printf(" -j: Use Jasper block numbering (implied with -b)\n"); } void calcecc(unsigned long *data, unsigned char *ecc) { int i=0, val=0; unsigned long v; for (i = 0; i < 0x1066; i++) { if (!(i & 31)) v = ~data[i>>5]; val ^= v & 1; v >>= 1; if (val & 1) val ^= 0x6954559; val >>= 1; } val = ~val; ecc[0] = (val << 6) & 0xFF; ecc[1] = (val >> 2) & 0xFF; ecc[2] = (val >> 10) & 0xFF; ecc[3] = (val >> 18) & 0xFF; } int main (int argc, const char * argv[]) { unsigned char data[BUFF_SIZE], badmap[MAX_BLOCKS/8], relocmap[MAX_BLOCKS/8], ecc[4]; unsigned int i,j,k,blocks,temp; unsigned int bb=0,jas=0,numBad=0,numEmpty=0,numECC=0,reloc=0; FILE *fp; /* Check Args */ if((argc < 2) || (argc > 4)) { printUsage(*argv); return 1; } /* Parse options */ for(i=1;i<argc-1;i++) { if(strlen(argv[i])== 2 && argv[i][0] == '-') { switch (argv[i][1]) { case 'b': bb++; jas++; break; case 'j': jas++; break; default: printUsage(*argv); return 1; } } else { printUsage(*argv); return 1; } } /* Try to open the file */ if((fp=fopen(argv[argc-1], "rb")) == NULL) { printf("Error opening %s\n",argv[argc-1]); return 1; } /* Check if the file size makes sense */ fseek(fp, 0, SEEK_END); blocks=ftell(fp); fseek(fp, 0, SEEK_SET); if(blocks % BSIZE(bb)) { printf("Warning: File size is not a multiple of the raw block size.\n"); printf(" Last block fragment will not be checked\n\n"); } blocks/= BSIZE(bb); printf("File %s contains 0x%03X blocks.\n",argv[argc-1],blocks); if(blocks > MAX_BLOCKS) { printf("Warning: Blocks above %d will not be considered in the bad block summary,\n",MAX_BLOCKS); printf(" or checked for relocation.\n"); } /* Determine if complete */ if(bb) { switch (blocks) { case 0x800: printf("File size matches a big block 256MB NAND flash.\n"); break; case 0x1000: printf("File size matches a big block 512MB NAND flash.\n"); break; default: printf("File size does not match known big block NAND flash sizes.\n"); } } else { if (blocks == 0x400) { printf("File size matches a small block 16MB NAND flash.\n"); } else { printf("File size does not match known small block NAND flash sizes.\n"); } } /* Clear map arrays */ memset(badmap, 0, sizeof(badmap)); memset(relocmap, 0, sizeof(relocmap)); /* Start the Block and Page loops */ for(i=0;i<blocks;i++) { reloc=0; for(j=0;j<PAGES(bb);j++) { fread(data, 1, PSIZE(bb), fp); // Read in the page /* Check if empty */ temp=0xFF; for(k=0;k<PSIZE(bb);temp&=data[k++]); if(temp == 0xFF) { numEmpty++; continue; // No need for further checks } /* Check for bad block per Hynix datasheet. */ if(data[BBFLAG(bb)] != 0xFF) { printf("Bad block:page %03X:%02X\n",i,j); numBad++; SETBIT(badmap,i); continue; // No need for further checks } /* Check block number in spare data. A mismatch may be a relocation. */ if(!reloc) { temp=*(int *)(data+BLOCKNUM(jas)) & 0xFFFF; if(i != temp) { printf("Block number mismatch in block:page %03X:%02X -> %03X vs %03X\n", \ i,j,temp,i); if (temp < MAX_BLOCKS) { if (GETBIT(badmap,temp)) { printf(" This block is probably a relocation of bad block %03X.\n",temp); printf(" Skipping relocation warnings for the rest of the block.\n"); reloc++; SETBIT(relocmap,temp); } } } } /* Calc the ECC data and compare */ calcecc((unsigned long *) data, ecc); ecc[0] |= data[PSIZE(bb)-4] & 0x3F; // These 6 bits are not part of the ECC if(memcmp(data+PSIZE(bb)-4,ecc,4)) { printf("ECC mismatch in block:page %03X:%02X -> 0x%08X vs 0x%08X\n", \ i,j,*(unsigned long *)(data+0x20c),*(unsigned long *)ecc); numECC++; } } } fclose(fp); printf("\nCheck complete!\n"); if(numBad) { printf("Found the following bad blocks (* marked blocks have been relocated):\n "); for(i=0,j=0;i<MAX_BLOCKS;i++) { if(GETBIT(badmap,i)) { printf("%c%03X ",GETBIT(relocmap,i)?'*':' ',i); j++; } if(j >= 10) { printf("\n "); j=0; } } } printf("\nFound %d ECC error(s), %d bad page(s), %d empty page(s).\n",numECC,numBad,numEmpty); return 0; }

Und im Anhang die Windows EXE


Angehängte Dateien
.zip   nandchk.zip (Größe: 4.82 KB / Downloads: 194)


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste