void nand_setio(DeviceState *dev, uint32_t value) { int i; NANDFlashState *s = (NANDFlashState *) dev; if (!s->ce && s->cle) { if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) { if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2) return; if (value == NAND_CMD_RANDOMREAD1) { s->addr &= ~((1 << s->addr_shift) - 1); s->addrlen = 0; return; } } if (value == NAND_CMD_READ0) s->offset = 0; else if (value == NAND_CMD_READ1) { s->offset = 0x100; value = NAND_CMD_READ0; } else if (value == NAND_CMD_READ2) { s->offset = 1 << s->page_shift; value = NAND_CMD_READ0; } s->cmd = value; if (s->cmd == NAND_CMD_READSTATUS || s->cmd == NAND_CMD_PAGEPROGRAM2 || s->cmd == NAND_CMD_BLOCKERASE1 || s->cmd == NAND_CMD_BLOCKERASE2 || s->cmd == NAND_CMD_NOSERIALREAD2 || s->cmd == NAND_CMD_RANDOMREAD2 || s->cmd == NAND_CMD_RESET) nand_command(s); if (s->cmd != NAND_CMD_RANDOMREAD2) { s->addrlen = 0; } } if (s->ale) { unsigned int shift = s->addrlen * 8; unsigned int mask = ~(0xff << shift); unsigned int v = value << shift; s->addr = (s->addr & mask) | v; s->addrlen ++; switch (s->addrlen) { case 1: if (s->cmd == NAND_CMD_READID) { nand_command(s); } break; case 2: /* fix cache address as a byte address */ s->addr <<= (s->buswidth - 1); break; case 3: if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) && (s->cmd == NAND_CMD_READ0 || s->cmd == NAND_CMD_PAGEPROGRAM1)) { nand_command(s); } break; case 4: if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) && nand_flash_ids[s->chip_id].size < 256 && /* 1Gb or less */ (s->cmd == NAND_CMD_READ0 || s->cmd == NAND_CMD_PAGEPROGRAM1)) { nand_command(s); } break; case 5: if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) && nand_flash_ids[s->chip_id].size >= 256 && /* 2Gb or more */ (s->cmd == NAND_CMD_READ0 || s->cmd == NAND_CMD_PAGEPROGRAM1)) { nand_command(s); } break; default: break; } } if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) { if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift)) { for (i = s->buswidth; i--; value >>= 8) { s->io[s->iolen ++] = (uint8_t) (value & 0xff); } } } else if (!s->cle && !s->ale && s->cmd == NAND_CMD_COPYBACKPRG1) {
void nand_dump(char* dumpname, int saddr, int length) { int oobsize = 16; int oobblock = 512; int flashsz = 32*1024*1024; unsigned long ofd; int start_addr, end_addr; int pretty_print; int ofs, i; unsigned char readbuf[512]; unsigned char oobbuf[16]; unsigned char pretty_buf[80]; if (strcmp(dumpname, "-") == 0) ofd = 1; else if ((ofd = open(dumpname, O_WRONLY | O_TRUNC | O_CREAT, 0644)) == -1) { perror("open outfile"); exit(2); } start_addr = saddr & ~(oobblock - 1); end_addr = (length == -1) ? flashsz : ((start_addr + length) & ~(oobblock - 1)); fprintf(stderr, "Would you like formatted output? "); pretty_print = tolower(getc(stdin)) == 'y'; fprintf(stderr, "Dumping data starting at 0x%08x and ending at 0x%08x...\n", start_addr, end_addr); // use auto-incr nand_command(NAND_CMD_READA); nand_address(0x00); nand_address((start_addr >> 9) & 0xFF); nand_address((start_addr >> 17) & 0xFF); for (ofs = start_addr; ofs < end_addr; ofs += oobblock) { while (!nand_ready()) ; chain_flags = LED_GREEN; for (i=0; i<oobblock; i++) { fprintf(stderr, "Reading: 0x%08x + %d \r", ofs, i); fflush(stderr); readbuf[i] = nand_read("byte"); } if (pretty_print) { for (i=0; i<oobblock; i+=16) { sprintf(pretty_buf, "0x%08x: %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n", (unsigned int) (ofs + i), readbuf[i], readbuf[i+1], readbuf[i+2], readbuf[i+3], readbuf[i+4], readbuf[i+5], readbuf[i+6], readbuf[i+7], readbuf[i+8], readbuf[i+9], readbuf[i+10], readbuf[i+11], readbuf[i+12], readbuf[i+13], readbuf[i+14], readbuf[i+15]); write(ofd, pretty_buf, 60); } } else write(ofd, readbuf, oobblock); chain_flags = LED_AMBER; for (i=0; i<oobsize; i++) { fprintf(stderr, "Reading: 0x%08x + (%d) \r", ofs, i); fflush(stderr); oobbuf[i] = nand_read("oob byte"); } if (pretty_print) { if (oobsize == 16) { sprintf(pretty_buf, " OOB Data: %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", oobbuf[0], oobbuf[1], oobbuf[2], oobbuf[3], oobbuf[4], oobbuf[5], oobbuf[6], oobbuf[7], oobbuf[8], oobbuf[9], oobbuf[10], oobbuf[11], oobbuf[12], oobbuf[13], oobbuf[14], oobbuf[15]); write(ofd, pretty_buf, 60); } else { sprintf(pretty_buf, " OOB Data: %02x %02x %02x %02x %02x %02x " "%02x %02x\n", oobbuf[0], oobbuf[1], oobbuf[2], oobbuf[3], oobbuf[4], oobbuf[5], oobbuf[6], oobbuf[7]); write(ofd, pretty_buf, 48); } } else write(ofd, oobbuf, oobsize); } chain_flags = LED_BLUE; nand_sane(); fprintf(stderr, "Reading: done! \n"); close(ofd); return; }