/* (C) 2003 XDA Developers itsme@xs4all.nl * * $Header$ */ #include #include #include "pkfuncs.h" #include "debug.h" #include "stringutils.h" #include "vectorutils.h" // 10 xx word program // 20 d0 block erase // 40 xx word program // 50 -- clear status // 60 01 lock block // 60 03 program read cfg reg [ addr=RCD ] // 60 2f lock-down block // 60 d0 unlock block // 70 .. read status reg // 80 d0 buffered enhanced factory program // 90 .. read device id [ addr=IA ] // 98 .. cfi query [ addr=QA ] // FF -- read array // b0 -- suspend program/erase // c0 ?? program lock reg [ addr=LRA ] // c0 ?? program protection reg [ addr=PRA ] // d0 -- resume program/erase // e8 xx buffered program // // offsets: // 0000 - manufacturer code : 0089 // 0001 - flash id code: 8810 // 0002 - block lock configuration // 0003 - ? // 0004 - ? // 0005 - configuration register // 0010 - QRY = cfi magic // 0013 - prvendor // 0014 - ID# // 0016 - tbladdr // .. // 001b - system information // 0027 - device geometry // 0080 - lock register 0 // 0081-0088 protection register 0 // 0089 - lock register 1 // 008a-0091 protection register 1 // .. // 0102-0109 protection register 16 // 010a - intel specific extended query table // 010a - 'PRI' - magic // 010d - version in ascii // 010f - optional feature and command support // 0113 - suspend functions // 0114 - block status // 0116 - optimum Vcc // 0117 - optimum Vpp // 0118 - nr of protection reg fields // 0119 - protection field 1 // 011d - protection field 2 // 0127 - burst read info // 012d - partition and erase block info // // experimental program, to read the intel strataflash chip information // const char* storagepath= "\\Storage Card\\dat"; // partition size seems to be 0x400000 // 0000-000f appear every 0x0800 bytes // 0010-0400 appear every 0x2000 bytes template void WriteVector(const TVector& data, const std::string& name) { if (data.empty()) return; FILE *f= fopen(name.c_str(), "a+b"); if (f) { fwrite(vectorptr(data), sizeof(TVector::value_type), data.size(), f); fclose(f); } } extern "C" BOOL KernelIoControl(DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned); inline void flashcmd(DWORD addr, BYTE cmd) { *(DWORD*)addr= cmd|(cmd<<16); } inline WORD readword(DWORD addr) { return *(WORD*)addr; } inline BYTE readbyte(DWORD addr) { return *(BYTE*)addr; } inline DWORD readdword(DWORD addr) { return *(DWORD*)addr; } inline void disable_irq() { if (!KernelIoControl(0x01012a24, 0, 0, 0, 0, 0)) error("disable_irq"); } inline void enable_irq() { if (!KernelIoControl(0x01012a20, 0, 0, 0, 0, 0)) error("enable_irq"); } inline BYTE read_status(DWORD dwPartition) { // addr can be any address in the partition flashcmd(dwPartition, 0x70); return readbyte(dwPartition); } inline void clear_status(DWORD dwAddr) { // addr can be any address in the flash flashcmd(dwAddr, 0x50); } inline void set_read_array_mode(DWORD dwPartition) { // addr can be any address in the partition flashcmd(dwPartition, 0xff); } inline void set_read_cfi_mode(DWORD dwPartition) { // addr can be any address in the partition flashcmd(dwPartition, 0x98); } inline void set_read_di_mode(DWORD dwPartition) { // addr can be any address in the partition flashcmd(dwPartition, 0x90); } ////////////////////////////////////////////////////////////////////////// // // write buffered: // flashcmd(dwAddr, 0xe8) // wait for SR.7 'write buffer available' // flashcmd(dwAddr, data.size()) // for (i=0; i=0xa0000000) for (i= 0; i < 8; i++) surround[i]= read_cfi_data(dwPartition, i-0x800); if (dwPartition-8>=0xa0000000) for (i= 0; i < 8; i++) surround[i+8]= read_cfi_data(dwPartition, i-8); for (DWORD dwReg= 0; dwReg < regs.size(); dwReg++) regs[dwReg]= read_cfi_data(dwPartition, dwReg); if (dwPartition+regs.size()<0xa4000000) for (i= 0 ; i < 8; i++) surround[i+16]= read_cfi_data(dwPartition, i+regs.size()); BYTE status2= read_status(dwPartition); set_read_array_mode(dwPartition); enable_irq(); WriteVector(regs, stringformat("%s\\cfi-%08lx.dat", storagepath, dwPartition)); debug("done readcfi(%08lx) %02x %02x : %hs\n", dwPartition, status1, status2, hexdump((BYTE*)vectorptr(surround), surround.size(), 2).c_str()); } ////////////////////////////////////////////////////////////////////////// inline WORD read_di_data(DWORD dwPartition, DWORD dwReg) { // read from di address + offset return readword(dwPartition+dwReg*2); } void flash_read_di(DWORD dwPartition, DWORD dwLength) { debug("start readdi(%08lx)\n", dwPartition); WordVector surround; surround.resize(24); WordVector regs; regs.resize(dwLength/2); disable_irq(); clear_status(dwPartition); DWORD status1= read_status(dwPartition); set_read_di_mode(dwPartition); int i; if (dwPartition-0x800>=0xa0000000) for (i= 0; i < 8; i++) surround[i]= read_di_data(dwPartition, i-0x800); if (dwPartition-8>=0xa0000000) for (i= 0; i < 8; i++) surround[i+8]= read_di_data(dwPartition, i-8); for (DWORD dwReg= 0; dwReg < regs.size(); dwReg++) regs[dwReg]= read_di_data(dwPartition, dwReg); if (dwPartition+regs.size()<0xa4000000) for (i= 0 ; i < 8; i++) surround[i+16]= read_di_data(dwPartition, i+regs.size()); BYTE status2= read_status(dwPartition); set_read_array_mode(dwPartition); enable_irq(); WriteVector(regs, stringformat("%s\\di-%08lx.dat", storagepath, dwPartition)); debug("done readdi(%08lx) %02x %02x : %hs\n", dwPartition, status1, status2, hexdump((BYTE*)vectorptr(surround), surround.size(), 2).c_str()); } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { DebugSetLogfile("tststrata.log"); DebugOutputDebugString(); debug("starting tststrata.log: %08lx\n", GetTickCount()); BOOL bMode = SetKMode(TRUE); DWORD dwPerm = SetProcPermissions(0xFFFFFFFF); for (DWORD dwAddr= 0xa0000000 ; dwAddr<0xa4000000 ; dwAddr += 0x8000) flash_read_cfi(dwAddr, 0x8000); for (DWORD dwAddr= 0xa0000000 ; dwAddr<0xa4000000 ; dwAddr += 0x8000) flash_read_di(dwAddr, 0x8000); SetProcPermissions(dwPerm); SetKMode(bMode); debug("ending tststrata.log: %08lx\n", GetTickCount()); return 0; }