OpenCores
URL https://opencores.org/ocsvn/usb_nand_reader/usb_nand_reader/trunk

Subversion Repositories usb_nand_reader

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /usb_nand_reader
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/pc/actions.c
0,0 → 1,234
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libusb-1.0/libusb.h>
#include "include/opcodes.h"
#include "include/actions.h"
#include "include/nand_vendors.h"
 
unsigned char ioBuffer[64];
int dataTransfered;
 
int
usb_write(libusb_device_handle* usb, unsigned char* data, int len)
{
int ds;
int i = 0;
int l = (len < 64)? 64 : len;
while(i < l)
{
libusb_bulk_transfer(usb, 0x01, data + i, l - i, &ds, 1000);
i += ds;
}
return i;
}
 
int
usb_read(libusb_device_handle* usb, unsigned char* data, int len)
{
int ds;
int i = 0, r;
if(len % 64 != 0)
{
fprintf(stderr, "\nIncorrect read length\n");
return 0;
}
while(i < len)
{
if(0 > (r = libusb_bulk_transfer(usb, 0x81, data + i, len - i, &ds, 10000)))
{
fprintf(stderr, "libusb_bulk_transfer() returned %d\n", r);
//exit(-4);
}
i += ds;
if(0 == ds)
exit(-3);
}
return i;
}
 
USB_ACTION(nand_reset)
{
ioBuffer[0] = NAND_CHIP_RESET;
usb_write(usb, ioBuffer, 1);
return 0;
}
 
USB_ACTION(nand_enable, int dieIndex)
{
ioBuffer[0] = NAND_CHIP_ENABLE;
ioBuffer[1] = (unsigned char)(dieIndex & 3);
usb_write(usb, ioBuffer, 2);
return 0;
}
 
USB_ACTION(nand_disble)
{
ioBuffer[0] = NAND_CHIP_DISABLE;
usb_write(usb, ioBuffer, 1);
return 0;
}
 
USB_ACTION(nand_read_id, unsigned char* idBuffer)
{
ioBuffer[0] = NAND_CHIP_READ_ID;
usb_write(usb, ioBuffer, 1);
usb_read(usb, ioBuffer, 64);
memcpy(idBuffer, ioBuffer, 5);
return 0;
}
 
USB_ACTION(nand_is_onfi, unsigned char* signature)
{
ioBuffer[0] = NAND_CHIP_READ_ID_ONFI;
usb_write(usb, ioBuffer, 1);
usb_read(usb, ioBuffer, 64);
memcpy(signature, ioBuffer, 4);
if(ioBuffer[0] == 'O' && ioBuffer[1] == 'N' && ioBuffer[2] == 'F' && ioBuffer[3] == 'I')
return 1;
return 0;
}
 
USB_ACTION(nand_read_onfi_param_page, unsigned char* paramPageBuffer)
{
ioBuffer[0] = NAND_CHIP_READ_PARAM_PAGE;
usb_write(usb, ioBuffer, 1);
usb_read(usb, paramPageBuffer, 256);
return 0;
}
 
USB_ACTION(nand_set_config_data, pnand_t nand)
{
ioBuffer[0] = NAND_SET_CONFIG_DATA;
*(int*)(&ioBuffer[1]) = nand->bytesPerPage + nand->oobPerPage;
ioBuffer[5] = (unsigned char)(nand->addressCycles & 0xff);
ioBuffer[6] = (unsigned char)(nand->busWidth);
usb_write(usb, ioBuffer, 6);
return 0;
}
 
USB_ACTION(nand_read_page, unsigned int pageAddress, pnand_t nand)
{
//struct timespec start = {0, 0}, end = {0, 0};
ioBuffer[0] = NAND_CHIP_READ_PAGE;
ioBuffer[1] = ioBuffer[2] = 0;
*(unsigned int*)(&ioBuffer[3]) = (pageAddress & 0x00ffffff);
//clock_gettime(CLOCK_MONOTONIC, &start);
usb_write(usb, ioBuffer, 64);
//printf("read %d bytes\n", usb_read(usb, nand->pageBuffer, nand->bytesPerPage + nand->oobPerPage));
usb_read(usb, nand->pageBuffer, nand->bytesPerPage + nand->oobPerPage);
//clock_gettime(CLOCK_MONOTONIC, &end);
//printf("\r\tPage read in %.10f seconds.", ((double)end.tv_sec + 1.0e-9 * end.tv_nsec) - ((double)start.tv_sec + 1.0e-9 * start.tv_nsec));
//fflush(stdout);
return 0;
}
 
USB_ACTION(nand_read_page_cache, unsigned int startPageAddress, int pageCount, FILE* storeTo, pnand_t nand)
{
int currentPage, blocks = 0;
unsigned int sa = startPageAddress;
if(0 != pageCount % nand->pagesPerBlock)
return -1;
while(blocks < pageCount / nand->pagesPerBlock)
{
fprintf(stderr,"\rBlock #%d (%0.4f%%)", blocks, (float)blocks / ((float)(pageCount / nand->pagesPerBlock) / 100.0f));
ioBuffer[0] = NAND_CHIP_READ_CACHE_SEQ;
ioBuffer[1] = ioBuffer[2] = 0;
*(unsigned int*)(&ioBuffer[3]) = (sa & 0x00ffffff);
*(int*)(&ioBuffer[6]) = nand->pagesPerBlock;
usb_write(usb, ioBuffer, 64);
for(currentPage = 0; currentPage < nand->pagesPerBlock; currentPage++)
{
usb_read(usb, nand->pageBuffer, nand->bytesPerPage + nand->oobPerPage);
if(NULL != storeTo)
store_page(storeTo, nand);
//fprintf(stderr,"\rBlock #%d %0.2f%% completed", blocks, (float)currentPage / ((float)nand->pagesPerBlock / 100.0f));
}
blocks++;
sa += nand->pagesPerBlock;
}
fprintf(stderr, "\n");
return 0;
}
 
USB_ACTION(nand_read_status, unsigned char* status)
{
ioBuffer[0] = NAND_CHIP_READ_STATUS;
usb_write(usb, ioBuffer, 64);
usb_read(usb, ioBuffer, 64);
if(status)
*status = ioBuffer[0];
return (int)ioBuffer[0];
}
 
USB_ACTION(nand_read_status_enhanced, unsigned int address, unsigned char* status)
{
ioBuffer[0] = NAND_CHIP_READ_STATUS;
*(unsigned int*)(&ioBuffer[1]) = address & 0xffffff;
usb_write(usb, ioBuffer, 64);
usb_read(usb, ioBuffer, 64);
if(status)
*status = ioBuffer[0];
return (int)ioBuffer[0];
}
 
USB_ACTION(nand_read_unique_id, unsigned char* uid)
{
ioBuffer[0] = NAND_CHIP_READ_UNIQUE_ID;
usb_write(usb, ioBuffer, 64);
usb_read(usb, ioBuffer, 64);
memcpy(uid, ioBuffer, 64);
return 0;
}
 
int nand_check_uid(unsigned char* buffer)
{
int i;
for(i = 0; i < 16; i++)
{
if(0xFF != (*(buffer + i) ^ *(buffer + i + 16)))
return 0;
}
return 1;
}
 
 
USB_ACTION(nand_block_erase, unsigned int blockAddress)
{
ioBuffer[0] = NAND_CHIP_BLOCK_ERASE;
*(unsigned int*)(&ioBuffer[1]) = (blockAddress & 0x00ffffff);
usb_write(usb, ioBuffer, 64);
return 0;
}
 
USB_ACTION(nand_toggle_wp)
{
ioBuffer[0] = NAND_CHIP_TOGGLE_WP;
usb_write(usb, ioBuffer, 64);
return 0;
}
 
USB_ACTION(nand_page_program, unsigned int pageAddress, pnand_t nand)
{
//int i;
ioBuffer[0] = NAND_CHIP_PAGE_PROGRAM;
ioBuffer[1] = ioBuffer[2] = 0;
*(unsigned int*)(&ioBuffer[3]) = (pageAddress & 0x00ffffff);
usb_write(usb, ioBuffer, 64);
/*
for(i = 0; i < nand->bytesPerPage + nand->oobPerPage; i += 64)
{
fprintf(stderr, "Written %d bytes\n", usb_write(usb, nand->pageBuffer + i, 64));
}
*/
fprintf(stderr, "Written %d bytes\n", usb_write(usb, nand->pageBuffer, nand->bytesPerPage + nand->oobPerPage));
return 0;
}
/trunk/pc/include/actions.h
0,0 → 1,26
#ifndef ACTIONS_H
#define ACTIONS_H
 
#include "include/nand_vendors.h"
 
#define USB_ACTION(pname, ...) int pname(libusb_device_handle* usb, ##__VA_ARGS__)
 
 
USB_ACTION(nand_reset);
USB_ACTION(nand_enable, int dieIndex);
USB_ACTION(nand_disble);
USB_ACTION(nand_read_id, unsigned char* idBuffer);
USB_ACTION(nand_is_onfi, unsigned char* signature);
USB_ACTION(nand_read_onfi_param_page, unsigned char* paramPageBuffer);
USB_ACTION(nand_set_config_data, pnand_t nand);
USB_ACTION(nand_read_page, unsigned int pageAddress, pnand_t nand);
USB_ACTION(nand_read_page_cache, unsigned int startPageAddress, int pageCount, FILE* storeTo, pnand_t nand);
USB_ACTION(nand_read_status, unsigned char* status);
USB_ACTION(nand_read_status_enhanced, unsigned int address, unsigned char* status);
USB_ACTION(nand_read_unique_id, unsigned char* uid);
int nand_check_uid(unsigned char* buffer);
USB_ACTION(nand_block_erase, unsigned int blockAddress);
USB_ACTION(nand_toggle_wp);
USB_ACTION(nand_page_program, unsigned int pageAddress, pnand_t nand);
 
#endif /* ACTIONS_H */
/trunk/pc/include/nand_vendors.h
0,0 → 1,33
#ifndef NAND_VENDORS_H
#define NAND_VENDORS_H
 
 
 
 
 
typedef struct
{
int bytesPerPage;
int oobPerPage;
int pagesPerBlock;
int blocksPerPlane;
int planesPerLun;
int numLuns;
int addressCycles;
int busWidth; // x8 or x16
unsigned char id[5];
unsigned char onfiSignature[4];
unsigned char* onfiParameterPage;
unsigned char* pageBuffer;
char* manufacturer;
char* device;
}nand_t, *pnand_t;
 
 
int get_nand_configuration(pnand_t nand);
void free_nand_info(pnand_t* nand);
void print_nand_configuration(pnand_t nand);
void dump_page(pnand_t nand);
void store_page(FILE* f, pnand_t nand);
 
#endif /* NAND_VENDORS_H */
/trunk/pc/include/opcodes.h
0,0 → 1,21
#ifndef OPCODES_H
#define OPCODES_H
 
#define NAND_CHIP_ENABLE 1
#define NAND_CHIP_DISABLE 2
#define NAND_CHIP_RESET 3
#define NAND_CHIP_READ_ID 4
#define NAND_CHIP_READ_ID_ONFI 5
#define NAND_CHIP_READ_PARAM_PAGE 6
#define NAND_CHIP_READ_PAGE 7
#define NAND_SET_CONFIG_DATA 8 // Sets configuration data for non ONFI chips (page size, address cycles, etc)
#define NAND_CHIP_READ_CACHE_SEQ 9 // READ_PAGE_CACHE_SEQUENTIAL
#define NAND_CHIP_READ_STATUS 10
#define NAND_CHIP_READ_UNIQUE_ID 11
#define NAND_CHIP_BLOCK_ERASE 12
#define NAND_CHIP_TOGGLE_WP 13 // Toggles write protect (WP = 0 on reset/powerup)
#define NAND_CHIP_PAGE_PROGRAM 14
#define NAND_CHIP_READ_STATUS_ENHANCED 15
 
 
#endif /* OPCODES_H */
/trunk/pc/main.c
0,0 → 1,174
#include <stdio.h>
#include <libusb-1.0/libusb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#include "include/opcodes.h"
#include "include/actions.h"
#include "include/nand_vendors.h"
 
int main(int argc, char **argv)
{
FILE* dump;
libusb_context* ctx;
libusb_device** list;
libusb_device_handle* hDevice = NULL;
struct libusb_device_descriptor descr;
int count, i;
unsigned char bufferOut[64];
unsigned char status;
pnand_t nand;
libusb_init(&ctx);
count = libusb_get_device_list(ctx, &list);
if(0 == count)
{
fprintf(stderr, "Could not get device list\n");
exit(-1);
}
for(i = 0; i < count; i++)
{
libusb_device* tmpDevice = list[i];
libusb_get_device_descriptor(tmpDevice, &descr);
if(0x1234 == descr.idVendor && 0x1 == descr.idProduct)
{
libusb_open(tmpDevice, &hDevice);
break;
}
}
libusb_free_device_list(list,1);
if(NULL == hDevice)
{
fprintf(stderr, "Could not find the device\n");
exit(-1);
}
else
{
printf("Device opened\n");
}
if(libusb_kernel_driver_active(hDevice, 0) == 1)
{
printf("Detaching driver\n");
libusb_detach_kernel_driver(hDevice, 0);
}
libusb_claim_interface(hDevice, 0);
//libusb_reset_device(hDevice);
//==============================
// USB initialization completed.
//==============================
nand = (pnand_t)malloc(sizeof(nand_t));
memset(nand, 0, sizeof(nand_t));
memset(bufferOut, 0, 64);
nand_enable(hDevice, 0);
nand_reset(hDevice);
nand_read_id(hDevice, nand->id);
if(nand_is_onfi(hDevice, nand->onfiSignature))
{
nand->onfiParameterPage = (unsigned char*)malloc(sizeof(unsigned char) * 256);
nand_read_onfi_param_page(hDevice, nand->onfiParameterPage);
}
if(1 != get_nand_configuration(nand))
{
printf("Could not get configuration for this chip\n");
nand_disble(hDevice);
libusb_close(hDevice);
libusb_exit(ctx);
return -1;
}
// Set configuration data if chip is not ONFI compliant or has corrupted ONFI parameter page/signature
if(NULL == nand->onfiParameterPage)
{
printf("Setting configuration data\n");
nand_set_config_data(hDevice, nand);
}
print_nand_configuration(nand);
/*
printf("Status: %02x\n", nand_read_status(hDevice, NULL));
nand_toggle_wp(hDevice);
fprintf(stderr, "Erasing block\n");
nand_block_erase(hDevice, 0);
//sleep(1);
printf("Status: %02x\n", nand_read_status_enhanced(hDevice, 0, NULL));
fprintf(stderr, "Programming page\n");
{
int x;
for(x = 0; x < nand->bytesPerPage + nand->oobPerPage; x++)
{
nand->pageBuffer[x] = (unsigned char)((x) & 0xf0);
}
}
nand_page_program(hDevice, 0, nand);
printf("Status: %02x\n", nand_read_status_enhanced(hDevice, 0, NULL));
nand_toggle_wp(hDevice);
*/
printf("Dumping flash\n");
i = 0;
dump = fopen("flash_dump.bin", "wb");
nand_read_status_enhanced(hDevice, 0, &status);
printf("Status: %02x\n", status);
/*
for(count = 0; count < nand->pagesPerBlock * nand->blocksPerPlane * nand->planesPerLun * nand->numLuns; count++)
{
if(count % 64 == 0)
{
printf("\rBlock #%d", i++);
fflush(stdout);
}
nand_read_page(hDevice, (unsigned int)count, nand);
store_page(dump, nand);
}
*/
printf("Dumping %d pages\n", nand->pagesPerBlock * nand->blocksPerPlane * nand->planesPerLun * nand->numLuns);
//nand_read_page_cache(hDevice, 0, nand->pagesPerBlock * nand->blocksPerPlane * nand->planesPerLun * nand->numLuns, dump, nand);
nand_read_page_cache(hDevice, 0, 640, dump, nand);
nand_read_status(hDevice, &status);
printf("Status: %02x\n", status);
fclose(dump);
printf("\rdone.\n");
free_nand_info(&nand);
nand_disble(hDevice);
//=================
// Close USB stuff.
//=================
 
libusb_close(hDevice);
libusb_exit(ctx);
return 0;
}
/trunk/pc/nand_vendors.c
0,0 → 1,181
 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "include/nand_vendors.h"
 
 
int
get_nand_configuration(pnand_t nand)
{
int result = 0;
printf("Getting configuration\n");
if(NULL != nand->onfiParameterPage)
{
nand->manufacturer = strndup((char*)nand->onfiParameterPage + 32, 12);
nand->device = strndup((char*)nand->onfiParameterPage + 44, 20);
nand->bytesPerPage = *(int*)(nand->onfiParameterPage + 80);
nand->oobPerPage = (int)*(short*)(nand->onfiParameterPage + 84);
nand->pagesPerBlock = *(int*)(nand->onfiParameterPage + 92);
nand->planesPerLun = 1;
nand->blocksPerPlane = *(int*)(nand->onfiParameterPage + 96);
nand->numLuns = (int)*(nand->onfiParameterPage +100);
nand->addressCycles = (*(nand->onfiParameterPage + 101) & 0x0f) + ((*(nand->onfiParameterPage + 101) >> 4) & 0x0f);
nand->busWidth = 8 << (*(nand->onfiParameterPage + 6) & 0x01);
result = 1;
}
else
{
switch(nand->id[0])
{
case 0x2c: // Micron
printf("Micron NAND flash detected\n");
nand->manufacturer = strdup("Micron");
if(nand->id[1] == 0xa1)
nand->device = strdup("MT29F1G08ABBDA");
else if(nand->id[1] == 0xaa)
nand->device = strdup("MT29F2G08ABBEA");
else if(nand->id[1] == 0xb1)
nand->device = strdup("MT29F1G16ABBDA");
else if(nand->id[1] == 0xba)
nand->device = strdup("MT29F2G16ABBEA");
else if(nand->id[1] == 0xca)
nand->device = strdup("MT29F2G16ABAEA");
else if(nand->id[1] == 0xda)
nand->device = strdup("MT29F2G08ABAEA");
else
{
printf("Unknown device\n");
break;
}
if((nand->id[3] & 3) == 1)
nand->bytesPerPage = 2048;
else
{
printf("Could not get number of bytes per page\n");
break;
}
if((nand->id[3] & 4) == 4)
nand->oobPerPage = 64;
else
{
printf("Could not get number of OOB bytes per page\n");
break;
}
nand->pagesPerBlock = ((64 << ((nand->id[3] >> 4) & 3)) * 1024) / nand->bytesPerPage;
nand->busWidth = 8 << ((nand->id[3] >> 4) & 1);
nand->numLuns = 1;
nand->planesPerLun = 1 << ((nand->id[4] >> 2) & 3);
nand->blocksPerPlane = (((1024 * 1024 * 1024) / 8) << ((nand->id[4] >> 4) & 7)) / (nand->pagesPerBlock * nand->bytesPerPage);
nand->addressCycles = 5;
result = 1;
break;
case 0x98: // Toshiba
printf("Toshiba NAND flash detected (JEDEC ID: %02X%02X%02X%02X%02X)\n", nand->id[0], nand->id[1], nand->id[2], nand->id[3], nand->id[4]);
nand->manufacturer = strdup("Toshiba");
if(nand->id[1] == 0xda)
{
nand->device = strdup("TC58NVG1S3HTA00");
nand->busWidth = 8;
nand->bytesPerPage = 2048;
nand->oobPerPage = 128;
nand->pagesPerBlock = 64;
nand->numLuns = 1;
nand->planesPerLun = 1;
nand->blocksPerPlane = 2048;
nand->addressCycles = 5;
result = 1;
}
else
break;
break;
default:
printf("Device manufacturer %02x could not be identified.\n", nand->id[0]);
break;
}
}
if(result)
nand->pageBuffer = (unsigned char*)malloc(sizeof(unsigned char) * (nand->bytesPerPage + nand->oobPerPage));
return result;
}
 
void free_nand_info(pnand_t* nand)
{
if(NULL == nand || NULL == *nand)
return;
if(NULL != (*nand)->manufacturer)
free((*nand)->manufacturer);
if(NULL != (*nand)->device)
free((*nand)->device);
if(NULL != (*nand)->onfiParameterPage)
free((*nand)->onfiParameterPage);
if(NULL != (*nand)->pageBuffer)
free((*nand)->pageBuffer);
free(*nand);
*nand = NULL;
}
 
void print_nand_configuration(pnand_t nand)
{
printf("\n***********************************\n");
printf("***** NAND configuration data *****\n");
printf("***********************************\n");
printf("Manufacturer: %s\n", nand->manufacturer);
printf("Device: %s\n", nand->device);
printf("ID: %02x %02x %02x %02x %02x\n", nand->id[0], nand->id[1], nand->id[2], nand->id[3], nand->id[4]);
printf("ONFI compliant: %s\n", (NULL == nand->onfiParameterPage)? "No" : "Yes");
printf("Data bus width: %d\n", nand->busWidth);
printf("Bytes per page: %d bytes\n", nand->bytesPerPage);
printf("OOB per page: %d bytes\n", nand->oobPerPage);
printf("Pages per block: %d\n", nand->pagesPerBlock);
printf("Blocks per plane: %d\n", nand->blocksPerPlane);
printf("Planes per LUN: %d\n", nand->planesPerLun);
printf("Number of LUNs: %d\n", nand->numLuns);
printf("Address cycles: %d\n", nand->addressCycles);
printf("ONFI signature bytes: %02x %02x %02x %02x\n\n", nand->onfiSignature[0], nand->onfiSignature[1], nand->onfiSignature[2], nand->onfiSignature[3]);
}
 
 
void dump_page(pnand_t nand)
{
int i, j;
for(i = 0; i < nand->bytesPerPage + nand->oobPerPage; i += 16)
{
for(j = 0; j < 16; j++)
{
printf("%02x ", nand->pageBuffer[i + j]);
}
printf("\t\t");
for(j = 0; j < 16; j++)
{
if(isprint(nand->pageBuffer[i + j]))
printf("%c", nand->pageBuffer[i + j]);
else
printf(".");
}
printf("\n");
}
}
 
void store_page(FILE* f, pnand_t nand)
{
fwrite(nand->pageBuffer, nand->bytesPerPage + nand->oobPerPage, 1, f);
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.