void do_client() { char obuffer[1024] = {0}, ibuffer[1024] = {0}; int obuffer_offset = 0, stop = 0; fflush (stdout); /* get anything out of the buffer */ conio_init(); show_buffer (obuffer, obuffer_offset); do { if (net_query (chan)) { int col = 10; int x = net_receive (chan, ibuffer, 1024, NULL); if (x<0) strcpy (ibuffer, "!!! (local) error reading packet"); else ibuffer[x] = 0; switch (ibuffer[0]) { case '*': col = 9; break; case '+': case '-': col = 11; break; case '!': col = 12; break; } write_to_window (ibuffer, col); show_buffer (obuffer, obuffer_offset); if (!strcmp (ibuffer, "*** go away")) stop = 1; if (!strcmp (ibuffer, "*** server shutting down")) stop = 1; } if (conio_kbhit()) { char ch = conio_getch(); switch (ch) { case 7: case 8: if (obuffer_offset) obuffer[--obuffer_offset] = 0; show_buffer (obuffer, obuffer_offset); break; case 13: net_send (chan, obuffer, strlen (obuffer)); obuffer[obuffer_offset = 0] = 0; show_buffer (obuffer, obuffer_offset); break; default: obuffer[obuffer_offset] = ch; obuffer[++obuffer_offset] = 0; show_buffer (obuffer, obuffer_offset); break; } } } while (!stop); erase_buffer(); conio_exit(); }
void write_to_window (char *buf, int col) { erase_buffer(); conio_gotoxy (1,24); conio_textcolor (col); conio_cputs (buf); conio_cputs ("\n"); conio_cputs ("\n"); }
void shell(void){ Task_t * c_t = get_current_task(); ttyScreen_t * screen = getScreen(c_t); shellLine_t * lineBuffer = getLineBuffer(c_t); char c; command_t * a = (command_t *) malloc(sizeof(command_t)); printf("BrunOS tty%d:~$ ", c_t->tty_number); while( (c=getc()) != '\n' ){ switch(c){ case '\b': if( lineBuffer->pos>0){ lineBuffer->buffer[--lineBuffer->pos]=0; putc('\b'); } break; case '\t': parse_command(a); auto_complete(a); break; default: if(lineBuffer->pos < lineBuffer->size-1){ lineBuffer->buffer[lineBuffer->pos++]=c; lineBuffer->buffer[lineBuffer->pos]=0; } putc(c); break; } } putc('\n'); parse_command(a); run_command(a); lineBuffer->pos=0; erase_buffer(); }
void auto_complete(command_t *command){ Task_t * c_t = get_current_task(); ttyScreen_t * screen = getScreen(c_t); shellLine_t * lineBuffer = getLineBuffer(c_t); int i, j, size, lenght, eq = TRUE; lenght = strlen(command->name); char * commName; if (streq(command->name, "")) return; for (i = 0; i < NUM_COMMANDS; i++) { commName = commands[i].name; for (j = 0; j < lenght && eq == TRUE; j++) { if (command->name[j] != commName[j]) eq = FALSE; if (j == strlen(commName) - 1) eq = FALSE; } if (eq == TRUE) { size = strlen(lineBuffer->buffer); erase_buffer(); clearfromto(screen->wpos - size * 2, screen->wpos); lineBuffer->pos = 0; lenght = strlen(commName); for (j = 0; j < lenght; j++) { lineBuffer->buffer[lineBuffer->pos++] = commName[j]; lineBuffer->buffer[lineBuffer->pos] = 0; putc(commName[j]); } } eq = !eq; } command->name[0] = 0; }
bool defragment(SimpleSignal* sig) { if (!sig->isFragmented()) return true; Uint32 fragId = sig->getFragmentId(); NodeId nodeId = refToNode(sig->header.theSendersBlockRef); DefragBuffer* dbuf; if(sig->isFirstFragment()){ // Make sure buffer does not exist if (find_buffer(nodeId, fragId)) abort(); dbuf = new DefragBuffer(nodeId, fragId); m_buffers.push_back(dbuf); } else { dbuf = find_buffer(nodeId, fragId); if (dbuf == NULL) abort(); } if (dbuf->m_buffer.append(sig->ptr[0].p, sig->ptr[0].sz * sizeof(Uint32))) abort(); // OOM if (!sig->isLastFragment()) return false; // Copy defragmented data into signal... int length = dbuf->m_buffer.length(); delete[] sig->ptr[0].p; sig->ptr[0].sz = (length+3)/4; sig->ptr[0].p = new Uint32[sig->ptr[0].sz]; memcpy(sig->ptr[0].p, dbuf->m_buffer.get_data(), length); // erase the buffer data erase_buffer(dbuf); return true; }
static int flash_write_nand(int mtdnum, struct img_type *img) { char mtd_device[LINESIZE]; struct flash_description *flash = get_flash_info(); struct mtd_dev_info *mtd = &flash->mtd_info[mtdnum].mtd; int pagelen; bool baderaseblock = false; long long imglen = 0; long long blockstart = -1; long long offs; unsigned char *filebuf = NULL; size_t filebuf_max = 0; size_t filebuf_len = 0; long long mtdoffset = 0; int ifd = img->fdin; int fd = -1; bool failed = true; int ret; unsigned char *writebuf = NULL; pagelen = mtd->min_io_size; imglen = img->size; snprintf(mtd_device, sizeof(mtd_device), "/dev/mtd%d", mtdnum); if ((imglen / pagelen) * mtd->min_io_size > mtd->size) { ERROR("Image %s does not fit into mtd%d\n", img->fname, mtdnum); return -EIO; } filebuf_max = mtd->eb_size / mtd->min_io_size * pagelen; filebuf = calloc(1, filebuf_max); erase_buffer(filebuf, filebuf_max); if ((fd = open(mtd_device, O_RDWR)) < 0) { ERROR( "%s: %s: %s", __func__, mtd_device, strerror(errno)); return -ENODEV; } /* * Get data from input and write to the device while there is * still input to read and we are still within the device * bounds. Note that in the case of standard input, the input * length is simply a quasi-boolean flag whose values are page * length or zero. */ while ((imglen > 0 || writebuf < filebuf + filebuf_len) && mtdoffset < mtd->size) { /* * New eraseblock, check for bad block(s) * Stay in the loop to be sure that, if mtdoffset changes because * of a bad block, the next block that will be written to * is also checked. Thus, we avoid errors if the block(s) after the * skipped block(s) is also bad */ while (blockstart != (mtdoffset & (~mtd->eb_size + 1))) { blockstart = mtdoffset & (~mtd->eb_size + 1); offs = blockstart; /* * if writebuf == filebuf, we are rewinding so we must * not reset the buffer but just replay it */ if (writebuf != filebuf) { erase_buffer(filebuf, filebuf_len); filebuf_len = 0; writebuf = filebuf; } baderaseblock = false; do { ret = mtd_is_bad(mtd, fd, offs / mtd->eb_size); if (ret < 0) { ERROR("mtd%d: MTD get bad block failed", mtdnum); goto closeall; } else if (ret == 1) { baderaseblock = true; } if (baderaseblock) { mtdoffset = blockstart + mtd->eb_size; if (mtdoffset > mtd->size) { ERROR("too many bad blocks, cannot complete request"); goto closeall; } } offs += mtd->eb_size; } while (offs < blockstart + mtd->eb_size); } /* Read more data from the input if there isn't enough in the buffer */ if (writebuf + mtd->min_io_size > filebuf + filebuf_len) { size_t readlen = mtd->min_io_size; size_t alreadyread = (filebuf + filebuf_len) - writebuf; size_t tinycnt = alreadyread; ssize_t cnt = 0; while (tinycnt < readlen) { cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt); if (cnt == 0) { /* EOF */ break; } else if (cnt < 0) { ERROR("File I/O error on input"); goto closeall; } tinycnt += cnt; } /* No padding needed - we are done */ if (tinycnt == 0) { imglen = 0; break; } /* Padding */ if (tinycnt < readlen) { erase_buffer(writebuf + tinycnt, readlen - tinycnt); } filebuf_len += readlen - alreadyread; imglen -= tinycnt - alreadyread; } /* Write out data */ ret = mtd_write(flash->libmtd, mtd, fd, mtdoffset / mtd->eb_size, mtdoffset % mtd->eb_size, writebuf, mtd->min_io_size, NULL, 0, MTD_OPS_PLACE_OOB); if (ret) { long long i; if (errno != EIO) { ERROR("mtd%d: MTD write failure", mtdnum); goto closeall; } /* Must rewind to blockstart if we can */ writebuf = filebuf; for (i = blockstart; i < blockstart + mtd->eb_size; i += mtd->eb_size) { if (mtd_erase(flash->libmtd, mtd, fd, i / mtd->eb_size)) { int errno_tmp = errno; TRACE("mtd%d: MTD Erase failure", mtdnum); if (errno_tmp != EIO) goto closeall; } } TRACE("Marking block at %08llx bad\n", mtdoffset & (~mtd->eb_size + 1)); if (mtd_mark_bad(mtd, fd, mtdoffset / mtd->eb_size)) { ERROR("mtd%d: MTD Mark bad block failure", mtdnum); goto closeall; } mtdoffset = blockstart + mtd->eb_size; continue; } mtdoffset += mtd->min_io_size; writebuf += pagelen; } failed = false; closeall: free(filebuf); close(fd); if (failed) { ERROR("Installing image %s into mtd%d failed\n", img->fname, mtdnum); return -1; } return 0; }
int nandwrite_mlc(char *image_path, int dev, loff_t mtdoffset, struct mtd_info_user *meminfo) { int cnt = 0; int image = -1; int imglen = 0, pagesize, blocksize, badblocks = 0; unsigned int offs; int ret; bool read_next = true; unsigned char *writebuf = NULL; int retCode = 0; uint32_t nblock, npage, skip; int total_blocks, pagesperblock, blockskip; image = open(image_path, O_RDONLY); if (image == -1) { perror("open error"); return -1; } imglen = lseek(image, 0, SEEK_END); lseek (image, 0, SEEK_SET); pagesize = meminfo->writesize; blocksize = meminfo->erasesize; // Check, if length fits into device total_blocks = meminfo->size / blocksize; pagesperblock = blocksize / pagesize; blockskip = (MLC_MAX_IMG_SIZ / pagesize + 1) * CONFIG_PAGE_REPLICATION * CONFIG_BLOCK_REPLICATION / pagesperblock; if ((blockskip * 2) > total_blocks || imglen > MLC_MAX_IMG_SIZ) { show_nand_info(stderr, meminfo); perror("Assigned max image size does not fit into device"); retCode = -2; goto closeall; } // Allocate a buffer big enough to contain all the data for one page writebuf = (unsigned char*)MALLOC(pagesize); erase_buffer(writebuf, pagesize); while ((imglen > 0) && (mtdoffset < meminfo->size)) { int readlen = pagesize; int tinycnt = 0; skip = 0; badblocks = 0; if (read_next) { erase_buffer(writebuf, readlen); /* Read up to one page data */ while (tinycnt < readlen) { cnt = read(image, writebuf + tinycnt, readlen - tinycnt); if (cnt == 0) { /* EOF */ break; } else if (cnt < 0) { perror ("File I/O error on input"); retCode = -3; goto closeall; } tinycnt += cnt; } imglen -= tinycnt; read_next = false; } for (nblock = 0; nblock < CONFIG_BLOCK_REPLICATION; nblock++) { // offs = mtdoffset + nblock * blocksize + skip * blocksize; offs = mtdoffset + skip * blocksize; // skip bad blocks ret = nand_block_isbad(dev, offs); if (ret < 0) { retCode = -5; goto closeall; } else if (ret == 1) { #if 0 loff_t checkblock; char have_copy = 0; if (!quiet) { fprintf(stderr, "Skip bad block at address 0x%x, (block %u)\n", offs, offs / blocksize); } badblocks++; // make sure we have at least one copy for (checkblock = 0; checkblock < CONFIG_BLOCK_REPLICATION; checkblock++) { offs = mtdoffset + checkblock * blocksize + skip * blocksize; ret = nand_block_isbad(dev, offs); if (ret < 0) goto closeall; else if (ret == 0) { have_copy = 1; break; } } if (!have_copy) { printf("Too many bad blocks\n"); goto closeall; } skip += blockskip; continue; #else if (!quiet) { uint32_t block_mask = meminfo->erasesize - 1; printf("Bad block 0x%x\n", (offs & (~block_mask))); } if (++badblocks >= CONFIG_BLOCK_REPLICATION) { printf("Too many bad blocks\n"); retCode = -4; goto closeall; } skip += blockskip; continue; #endif } for (npage = 0; npage < CONFIG_PAGE_REPLICATION; npage++) { offs = mtdoffset + npage * pagesize + skip * blocksize; /* Write out the Page data */ if (pwrite(dev, writebuf, pagesize, offs) != pagesize) { fprintf(stderr, "Bad page for copy %u of block %x for address %x\n", npage, nblock, offs); } } skip += blockskip; read_next = true; } // for nblock mtdoffset += pagesize * CONFIG_PAGE_REPLICATION; } // while (imglen > 0) closeall: if (writebuf) { free(writebuf); } close(image); if (imglen > 0) { fprintf(stderr, "Data was only partially written due to error\n"); } return retCode; }
int write_fec(char *infile, int dev, loff_t mtdoffset, struct mtd_info_user *meminfo) { int image = -1; int n, retCode = 0; unsigned char *inbuf, *outbuf; int pagesize = meminfo->writesize; int rdsize = pagesize / FEC_ENCODE_SCALING; if (lseek(dev, mtdoffset, SEEK_SET) != mtdoffset) { perror("lseek error"); return -4; } if ((image = open(infile, O_RDONLY)) < 0) { perror("open error"); return -1; } inbuf = (unsigned char *)MALLOC(rdsize); outbuf = (unsigned char *)MALLOC(pagesize); while ( (n = read(image, inbuf, rdsize)) > 0) { unsigned char *ppos = outbuf; int i, j; erase_buffer(outbuf, pagesize); for (i = 0; i < n; i++) { unsigned char plain = inbuf[i]; unsigned char cypher; for (j = 0; j < 8; j++) { if (plain & 1) cypher = 0x55; else cypher = 0xAA; plain >>= 1; *ppos++ = cypher; } } while (nand_block_isbad(dev, mtdoffset)) { mtdoffset += meminfo->erasesize; if (lseek(dev, mtdoffset, SEEK_SET) != mtdoffset) { perror("lseek error"); retCode = -4; goto out; } } /* Should check bad block first */ if (write(dev, outbuf, pagesize) != pagesize) { perror("Write Error"); retCode = -2; goto out; } mtdoffset += pagesize; } if (n < 0) { perror("Read Error"); retCode = -3; } out: close(image); free(inbuf); free(outbuf); return retCode; }
/* * Main program */ int main(int argc, char * const argv[]) { int cnt = 0; int fd = -1; int ifd = -1; int imglen = 0, pagelen; bool baderaseblock = false; int blockstart = -1; struct mtd_info_user meminfo; struct mtd_oob_buf oob; loff_t offs; int ret, readlen; int oobinfochanged = 0; struct nand_oobinfo old_oobinfo; int readcnt = 0; bool failed = true; process_options(argc, argv); erase_buffer(oobbuf, sizeof(oobbuf)); if (pad && writeoob) { fprintf(stderr, "Can't pad when oob data is present.\n"); exit (EXIT_FAILURE); } /* Open the device */ if ((fd = open(mtd_device, O_RDWR)) == -1) { perror(mtd_device); exit (EXIT_FAILURE); } /* Fill in MTD device capability structure */ if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { perror("MEMGETINFO"); close(fd); exit (EXIT_FAILURE); } /* Set erasesize to specified number of blocks - to match jffs2 * (virtual) block size */ meminfo.erasesize *= blockalign; /* Make sure device page sizes are valid */ if (!(meminfo.oobsize == 16 && meminfo.writesize == 512) && !(meminfo.oobsize == 8 && meminfo.writesize == 256) && !(meminfo.oobsize == 64 && meminfo.writesize == 2048) && !(meminfo.oobsize == 128 && meminfo.writesize == 4096)) { fprintf(stderr, "Unknown flash (not normal NAND)\n"); close(fd); exit (EXIT_FAILURE); } if (autoplace) { /* Read the current oob info */ if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) { perror ("MEMGETOOBSEL"); close (fd); exit (EXIT_FAILURE); } // autoplace ECC ? if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) { if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) { perror ("MEMSETOOBSEL"); close (fd); exit (EXIT_FAILURE); } oobinfochanged = 1; } } if (noecc) { ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW); if (ret == 0) { oobinfochanged = 2; } else { switch (errno) { case ENOTTY: if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) { perror ("MEMGETOOBSEL"); close (fd); exit (EXIT_FAILURE); } if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) { perror ("MEMSETOOBSEL"); close (fd); exit (EXIT_FAILURE); } oobinfochanged = 1; break; default: perror ("MTDFILEMODE"); close (fd); exit (EXIT_FAILURE); } } } /* * force oob layout for jffs2 or yaffs ? * Legacy support */ if (forcejffs2 || forceyaffs) { struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo; if (autoplace) { fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n"); goto restoreoob; } if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) { fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n"); goto restoreoob; } if (meminfo.oobsize == 8) { if (forceyaffs) { fprintf (stderr, "YAFSS cannot operate on 256 Byte page size"); goto restoreoob; } /* Adjust number of ecc bytes */ jffs2_oobinfo.eccbytes = 3; } if (ioctl (fd, MEMSETOOBSEL, oobsel) != 0) { perror ("MEMSETOOBSEL"); goto restoreoob; } } oob.length = meminfo.oobsize; oob.ptr = noecc ? oobreadbuf : oobbuf; /* Determine if we are reading from standard input or from a file. */ if (strcmp(img, standard_input) == 0) { ifd = STDIN_FILENO; } else { ifd = open(img, O_RDONLY); } if (ifd == -1) { perror(img); goto restoreoob; } /* For now, don't allow writing oob when reading from standard input. */ if (ifd == STDIN_FILENO && writeoob) { fprintf(stderr, "Can't write oob when reading from standard input.\n"); goto closeall; } pagelen = meminfo.writesize + ((writeoob) ? meminfo.oobsize : 0); /* * For the standard input case, the input size is merely an * invariant placeholder and is set to the write page * size. Otherwise, just use the input file size. * * TODO: Add support for the -l,--length=length option (see * previous discussion by Tommi Airikka <*****@*****.**> at * <http://lists.infradead.org/pipermail/linux-mtd/2008-September/ * 022913.html> */ if (ifd == STDIN_FILENO) { imglen = pagelen; } else { imglen = lseek(ifd, 0, SEEK_END); lseek (ifd, 0, SEEK_SET); } // Check, if file is page-aligned if ((!pad) && ((imglen % pagelen) != 0)) { fprintf (stderr, "Input file is not page-aligned. Use the padding " "option.\n"); goto closeall; } // Check, if length fits into device if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) { fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %u bytes\n", imglen, pagelen, meminfo.writesize, meminfo.size); perror ("Input file does not fit into device"); goto closeall; } /* * Get data from input and write to the device while there is * still input to read and we are still within the device * bounds. Note that in the case of standard input, the input * length is simply a quasi-boolean flag whose values are page * length or zero. */ while (imglen && (mtdoffset < meminfo.size)) { // new eraseblock , check for bad block(s) // Stay in the loop to be sure if the mtdoffset changes because // of a bad block, that the next block that will be written to // is also checked. Thus avoiding errors if the block(s) after the // skipped block(s) is also bad (number of blocks depending on // the blockalign while (blockstart != (mtdoffset & (~meminfo.erasesize + 1))) { blockstart = mtdoffset & (~meminfo.erasesize + 1); offs = blockstart; baderaseblock = false; if (!quiet) fprintf (stdout, "Writing data to block %d at offset 0x%x\n", blockstart / meminfo.erasesize, blockstart); /* Check all the blocks in an erase block for bad blocks */ do { if ((ret = ioctl(fd, MEMGETBADBLOCK, &offs)) < 0) { perror("ioctl(MEMGETBADBLOCK)"); goto closeall; } if (ret == 1) { baderaseblock = true; if (!quiet) fprintf (stderr, "Bad block at %x, %u block(s) " "from %x will be skipped\n", (int) offs, blockalign, blockstart); } if (baderaseblock) { mtdoffset = blockstart + meminfo.erasesize; } offs += meminfo.erasesize / blockalign ; } while ( offs < blockstart + meminfo.erasesize ); } readlen = meminfo.writesize; if (ifd != STDIN_FILENO) { int tinycnt = 0; if (pad && (imglen < readlen)) { readlen = imglen; erase_buffer(writebuf + readlen, meminfo.writesize - readlen); } /* Read Page Data from input file */ while(tinycnt < readlen) { cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt); if (cnt == 0) { // EOF break; } else if (cnt < 0) { perror ("File I/O error on input file"); goto closeall; } tinycnt += cnt; } } else { int tinycnt = 0; while(tinycnt < readlen) { cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt); if (cnt == 0) { // EOF break; } else if (cnt < 0) { perror ("File I/O error on stdin"); goto closeall; } tinycnt += cnt; } /* No padding needed - we are done */ if (tinycnt == 0) { imglen = 0; break; } /* No more bytes - we are done after writing the remaining bytes */ if (cnt == 0) { imglen = 0; } /* Padding */ if (pad && (tinycnt < readlen)) { erase_buffer(writebuf + tinycnt, meminfo.writesize - tinycnt); } } if (writeoob) { int tinycnt = 0; while(tinycnt < meminfo.oobsize) { cnt = read(ifd, oobreadbuf + tinycnt, meminfo.oobsize - tinycnt); if (cnt == 0) { // EOF break; } else if (cnt < 0) { perror ("File I/O error on input file"); goto closeall; } tinycnt += cnt; } if (!noecc) { int i, start, len; /* * We use autoplacement and have the oobinfo with the autoplacement * information from the kernel available * * Modified to support out of order oobfree segments, * such as the layout used by diskonchip.c */ if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) { for (i = 0;old_oobinfo.oobfree[i][1]; i++) { /* Set the reserved bytes to 0xff */ start = old_oobinfo.oobfree[i][0]; len = old_oobinfo.oobfree[i][1]; memcpy(oobbuf + start, oobreadbuf + start, len); } } else { /* Set at least the ecc byte positions to 0xff */ start = old_oobinfo.eccbytes; len = meminfo.oobsize - start; memcpy(oobbuf + start, oobreadbuf + start, len); } } /* Write OOB data first, as ecc will be placed in there*/ oob.start = mtdoffset; if (ioctl(fd, MEMWRITEOOB, &oob) != 0) { perror ("ioctl(MEMWRITEOOB)"); goto closeall; } imglen -= meminfo.oobsize; } /* Write out the Page data */ if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) != meminfo.writesize) { int rewind_blocks; off_t rewind_bytes; erase_info_t erase; perror ("pwrite"); if (errno != EIO) { goto closeall; } /* Must rewind to blockstart if we can */ rewind_blocks = (mtdoffset - blockstart) / meminfo.writesize; /* Not including the one we just attempted */ rewind_bytes = (rewind_blocks * meminfo.writesize) + readlen; if (writeoob) rewind_bytes += (rewind_blocks + 1) * meminfo.oobsize; if (lseek(ifd, -rewind_bytes, SEEK_CUR) == -1) { perror("lseek"); fprintf(stderr, "Failed to seek backwards to recover from write error\n"); goto closeall; } erase.start = blockstart; erase.length = meminfo.erasesize; fprintf(stderr, "Erasing failed write from %08lx-%08lx\n", (long)erase.start, (long)erase.start+erase.length-1); if (ioctl(fd, MEMERASE, &erase) != 0) { perror("MEMERASE"); if (errno != EIO) { goto closeall; } } if (markbad) { loff_t bad_addr = mtdoffset & (~(meminfo.erasesize / blockalign) + 1); fprintf(stderr, "Marking block at %08lx bad\n", (long)bad_addr); if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) { perror("MEMSETBADBLOCK"); goto closeall; } } mtdoffset = blockstart + meminfo.erasesize; imglen += rewind_blocks * meminfo.writesize; continue; } if (ifd != STDIN_FILENO) { imglen -= readlen; } mtdoffset += meminfo.writesize; } failed = false; closeall: close(ifd); restoreoob: if (oobinfochanged == 1) { if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) { perror ("MEMSETOOBSEL"); close (fd); exit (EXIT_FAILURE); } } close(fd); if (failed || ((ifd != STDIN_FILENO) && (imglen > 0))) { perror ("Data was only partially written due to error\n"); exit (EXIT_FAILURE); } /* Return happy */ return EXIT_SUCCESS; }
/* * Main program */ int main(int argc, char * const argv[]) { int cnt = 0; int fd = -1; int ifd = -1; int imglen = 0, pagelen; bool baderaseblock = false; long long blockstart = -1; struct mtd_dev_info mtd; long long offs; int ret; int oobinfochanged = 0; struct nand_oobinfo old_oobinfo; bool failed = true; // contains all the data read from the file so far for the current eraseblock unsigned char *filebuf = NULL; size_t filebuf_max = 0; size_t filebuf_len = 0; // points to the current page inside filebuf unsigned char *writebuf = NULL; // points to the OOB for the current page in filebuf unsigned char *oobreadbuf = NULL; unsigned char *oobbuf = NULL; libmtd_t mtd_desc; int ebsize_aligned; process_options(argc, argv); if (pad && writeoob) { fprintf(stderr, "Can't pad when oob data is present.\n"); exit(EXIT_FAILURE); } /* Open the device */ if ((fd = open(mtd_device, O_RDWR)) == -1) { perror(mtd_device); exit(EXIT_FAILURE); } mtd_desc = libmtd_open(); if (!mtd_desc) return errmsg("can't initialize libmtd"); /* Fill in MTD device capability structure */ if (mtd_get_dev_info(mtd_desc, mtd_device, &mtd) < 0) return errmsg("mtd_get_dev_info failed"); /* * Pretend erasesize is specified number of blocks - to match jffs2 * (virtual) block size * Use this value throughout unless otherwise necessary */ ebsize_aligned = mtd.eb_size * blockalign; if (mtdoffset & (mtd.min_io_size - 1)) { fprintf(stderr, "The start address is not page-aligned !\n" "The pagesize of this NAND Flash is 0x%x.\n", mtd.min_io_size); close(fd); exit(EXIT_FAILURE); } if (autoplace) { /* Read the current oob info */ if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) { perror("MEMGETOOBSEL"); close(fd); exit(EXIT_FAILURE); } // autoplace ECC ? if (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE) { if (ioctl(fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) { perror("MEMSETOOBSEL"); close(fd); exit(EXIT_FAILURE); } oobinfochanged = 1; } } if (noecc) { ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW); if (ret == 0) { oobinfochanged = 2; } else { switch (errno) { case ENOTTY: if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) { perror("MEMGETOOBSEL"); close(fd); exit(EXIT_FAILURE); } if (ioctl(fd, MEMSETOOBSEL, &none_oobinfo) != 0) { perror("MEMSETOOBSEL"); close(fd); exit(EXIT_FAILURE); } oobinfochanged = 1; break; default: perror("MTDFILEMODE"); close(fd); exit(EXIT_FAILURE); } } } /* * force oob layout for jffs2 or yaffs ? * Legacy support */ if (forcejffs2 || forceyaffs) { struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo; if (autoplace) { fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n"); goto restoreoob; } if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) { fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n"); goto restoreoob; } if (mtd.oob_size == 8) { if (forceyaffs) { fprintf(stderr, "YAFSS cannot operate on 256 Byte page size"); goto restoreoob; } /* Adjust number of ecc bytes */ jffs2_oobinfo.eccbytes = 3; } if (ioctl(fd, MEMSETOOBSEL, oobsel) != 0) { perror("MEMSETOOBSEL"); goto restoreoob; } } /* Determine if we are reading from standard input or from a file. */ if (strcmp(img, standard_input) == 0) { ifd = STDIN_FILENO; } else { ifd = open(img, O_RDONLY); } if (ifd == -1) { perror(img); goto restoreoob; } pagelen = mtd.min_io_size + ((writeoob) ? mtd.oob_size : 0); /* * For the standard input case, the input size is merely an * invariant placeholder and is set to the write page * size. Otherwise, just use the input file size. * * TODO: Add support for the -l,--length=length option (see * previous discussion by Tommi Airikka <*****@*****.**> at * <http://lists.infradead.org/pipermail/linux-mtd/2008-September/ * 022913.html> */ if (ifd == STDIN_FILENO) { imglen = pagelen; } else { imglen = lseek(ifd, 0, SEEK_END); lseek(ifd, 0, SEEK_SET); } // Check, if file is page-aligned if ((!pad) && ((imglen % pagelen) != 0)) { fprintf(stderr, "Input file is not page-aligned. Use the padding " "option.\n"); goto closeall; } // Check, if length fits into device if (((imglen / pagelen) * mtd.min_io_size) > (mtd.size - mtdoffset)) { fprintf(stderr, "Image %d bytes, NAND page %d bytes, OOB area %d" " bytes, device size %lld bytes\n", imglen, pagelen, mtd.oob_size, mtd.size); perror("Input file does not fit into device"); goto closeall; } /* * Allocate a buffer big enough to contain all the data (OOB included) * for one eraseblock. The order of operations here matters; if ebsize * and pagelen are large enough, then "ebsize_aligned * pagelen" could * overflow a 32-bit data type. */ filebuf_max = ebsize_aligned / mtd.min_io_size * pagelen; filebuf = xmalloc(filebuf_max); erase_buffer(filebuf, filebuf_max); oobbuf = xmalloc(mtd.oob_size); erase_buffer(oobbuf, mtd.oob_size); /* * Get data from input and write to the device while there is * still input to read and we are still within the device * bounds. Note that in the case of standard input, the input * length is simply a quasi-boolean flag whose values are page * length or zero. */ while (((imglen > 0) || (writebuf < (filebuf + filebuf_len))) && (mtdoffset < mtd.size)) { /* * New eraseblock, check for bad block(s) * Stay in the loop to be sure that, if mtdoffset changes because * of a bad block, the next block that will be written to * is also checked. Thus, we avoid errors if the block(s) after the * skipped block(s) is also bad (number of blocks depending on * the blockalign). */ while (blockstart != (mtdoffset & (~ebsize_aligned + 1))) { blockstart = mtdoffset & (~ebsize_aligned + 1); offs = blockstart; // if writebuf == filebuf, we are rewinding so we must not // reset the buffer but just replay it if (writebuf != filebuf) { erase_buffer(filebuf, filebuf_len); filebuf_len = 0; writebuf = filebuf; } baderaseblock = false; if (!quiet) fprintf(stdout, "Writing data to block %lld at offset 0x%llx\n", blockstart / ebsize_aligned, blockstart); /* Check all the blocks in an erase block for bad blocks */ if (noskipbad) continue; do { if ((ret = mtd_is_bad(&mtd, fd, offs / ebsize_aligned)) < 0) { sys_errmsg("%s: MTD get bad block failed", mtd_device); goto closeall; } else if (ret == 1) { baderaseblock = true; if (!quiet) fprintf(stderr, "Bad block at %llx, %u block(s) " "from %llx will be skipped\n", offs, blockalign, blockstart); } if (baderaseblock) { mtdoffset = blockstart + ebsize_aligned; } offs += ebsize_aligned / blockalign; } while (offs < blockstart + ebsize_aligned); } // Read more data from the input if there isn't enough in the buffer if ((writebuf + mtd.min_io_size) > (filebuf + filebuf_len)) { int readlen = mtd.min_io_size; int alreadyread = (filebuf + filebuf_len) - writebuf; int tinycnt = alreadyread; while (tinycnt < readlen) { cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt); if (cnt == 0) { // EOF break; } else if (cnt < 0) { perror("File I/O error on input"); goto closeall; } tinycnt += cnt; } /* No padding needed - we are done */ if (tinycnt == 0) { /* * For standard input, set imglen to 0 to signal * the end of the "file". For nonstandard input, * leave it as-is to detect an early EOF. */ if (ifd == STDIN_FILENO) { imglen = 0; } break; } /* Padding */ if (tinycnt < readlen) { if (!pad) { fprintf(stderr, "Unexpected EOF. Expecting at least " "%d more bytes. Use the padding option.\n", readlen - tinycnt); goto closeall; } erase_buffer(writebuf + tinycnt, readlen - tinycnt); } filebuf_len += readlen - alreadyread; if (ifd != STDIN_FILENO) { imglen -= tinycnt - alreadyread; } else if (cnt == 0) { /* No more bytes - we are done after writing the remaining bytes */ imglen = 0; } } if (writeoob) { oobreadbuf = writebuf + mtd.min_io_size; // Read more data for the OOB from the input if there isn't enough in the buffer if ((oobreadbuf + mtd.oob_size) > (filebuf + filebuf_len)) { int readlen = mtd.oob_size; int alreadyread = (filebuf + filebuf_len) - oobreadbuf; int tinycnt = alreadyread; while (tinycnt < readlen) { cnt = read(ifd, oobreadbuf + tinycnt, readlen - tinycnt); if (cnt == 0) { // EOF break; } else if (cnt < 0) { perror("File I/O error on input"); goto closeall; } tinycnt += cnt; } if (tinycnt < readlen) { fprintf(stderr, "Unexpected EOF. Expecting at least " "%d more bytes for OOB\n", readlen - tinycnt); goto closeall; } filebuf_len += readlen - alreadyread; if (ifd != STDIN_FILENO) { imglen -= tinycnt - alreadyread; } else if (cnt == 0) { /* No more bytes - we are done after writing the remaining bytes */ imglen = 0; } } if (!noecc) { int i, start, len; int tags_pos = 0; /* * We use autoplacement and have the oobinfo with the autoplacement * information from the kernel available * * Modified to support out of order oobfree segments, * such as the layout used by diskonchip.c */ if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) { for (i = 0; old_oobinfo.oobfree[i][1]; i++) { /* Set the reserved bytes to 0xff */ start = old_oobinfo.oobfree[i][0]; len = old_oobinfo.oobfree[i][1]; if (rawoob) memcpy(oobbuf + start, oobreadbuf + start, len); else memcpy(oobbuf + start, oobreadbuf + tags_pos, len); tags_pos += len; } } else { /* Set at least the ecc byte positions to 0xff */ start = old_oobinfo.eccbytes; len = mtd.oob_size - start; memcpy(oobbuf + start, oobreadbuf + start, len); } } /* Write OOB data first, as ecc will be placed in there */ if (mtd_write_oob(mtd_desc, &mtd, fd, mtdoffset, mtd.oob_size, noecc ? oobreadbuf : oobbuf)) { sys_errmsg("%s: MTD writeoob failure", mtd_device); goto closeall; } } /* Write out the Page data */ if (mtd_write(&mtd, fd, mtdoffset / mtd.eb_size, mtdoffset % mtd.eb_size, writebuf, mtd.min_io_size)) { int i; if (errno != EIO) { sys_errmsg("%s: MTD write failure", mtd_device); goto closeall; } /* Must rewind to blockstart if we can */ writebuf = filebuf; fprintf(stderr, "Erasing failed write from %#08llx to %#08llx\n", blockstart, blockstart + ebsize_aligned - 1); for (i = blockstart; i < blockstart + ebsize_aligned; i += mtd.eb_size) { if (mtd_erase(mtd_desc, &mtd, fd, mtd.eb_size)) { int errno_tmp = errno; sys_errmsg("%s: MTD Erase failure", mtd_device); if (errno_tmp != EIO) { goto closeall; } } } if (markbad) { fprintf(stderr, "Marking block at %08llx bad\n", mtdoffset & (~mtd.eb_size + 1)); if (mtd_mark_bad(&mtd, fd, mtdoffset / mtd.eb_size)) { sys_errmsg("%s: MTD Mark bad block failure", mtd_device); goto closeall; } } mtdoffset = blockstart + ebsize_aligned; continue; } mtdoffset += mtd.min_io_size; writebuf += pagelen; } failed = false; closeall: close(ifd); restoreoob: libmtd_close(mtd_desc); free(filebuf); free(oobbuf); if (oobinfochanged == 1) { if (ioctl(fd, MEMSETOOBSEL, &old_oobinfo) != 0) { perror("MEMSETOOBSEL"); close(fd); exit(EXIT_FAILURE); } } close(fd); if (failed || ((ifd != STDIN_FILENO) && (imglen > 0)) || (writebuf < (filebuf + filebuf_len))) { perror("Data was only partially written due to error\n"); exit(EXIT_FAILURE); } /* Return happy */ return EXIT_SUCCESS; }
int divideByZero(int argc, char *argv){ erase_buffer(); int x = 1; int y = 1; int z = x / --y; }