From patchwork Mon Sep 8 04:29:19 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grant Erickson X-Patchwork-Id: 200 Return-Path: X-Original-To: patchwork@ozlabs.org Delivered-To: patchwork@ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D3E77DDDED for ; Mon, 8 Sep 2008 14:29:30 +1000 (EST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.68 #1 (Red Hat Linux)) id 1KcYNQ-0003X3-QY; Mon, 08 Sep 2008 04:29:24 +0000 Received: from relay02.pair.com ([209.68.5.16]) by bombadil.infradead.org with smtp (Exim 4.68 #1 (Red Hat Linux)) id 1KcYNO-0003Oc-Mv for linux-mtd@lists.infradead.org; Mon, 08 Sep 2008 04:29:23 +0000 Received: (qmail 64434 invoked by uid 0); 8 Sep 2008 04:29:20 -0000 Received: from unknown (HELO localhost.localdomain) (unknown) by unknown with SMTP; 8 Sep 2008 04:29:20 -0000 X-pair-Authenticated: 66.134.71.115 From: Grant Erickson To: linux-mtd@lists.infradead.org Subject: [PATCH 6/6] [MTD-UTILS] nandwrite: Add Support for Reading from Standard Input Date: Sun, 7 Sep 2008 21:29:19 -0700 Message-Id: <1220848159-22407-1-git-send-email-gerickson@nuovations.com> X-Mailer: git-send-email 1.6.0.1 Organization: Nuovation System Designs, LLC X-Spam-Score: 0.0 (/) Cc: Tommi Airikka , Richard Titmuss X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+patchwork=ozlabs.org@lists.infradead.org Added suppport for reading in band data from standard input based on a patch originally generated by Richard Titmuss at . Signed-off-by: Grant Erickson diff --git a/nandwrite.c b/nandwrite.c index b7cd72e..fc23e85 100644 --- a/nandwrite.c +++ b/nandwrite.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -74,7 +76,7 @@ static struct nand_oobinfo autoplace_oobinfo = { static void display_help (void) { printf( -"Usage: nandwrite [OPTION] MTD_DEVICE INPUTFILE\n" +"Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n" "Writes to the specified MTD device.\n" "\n" " -a, --autoplace Use auto oob layout\n" @@ -110,6 +112,7 @@ static void display_version (void) exit (EXIT_SUCCESS); } +static const char *standard_input = "-"; static const char *mtd_device, *img; static int mtdoffset = 0; static bool quiet = false; @@ -198,16 +201,46 @@ static void process_options (int argc, char * const argv[]) blockalign = atoi (optarg); break; case '?': - error = 1; + error++; break; } } - if ((argc - optind) != 2 || error) + if (mtdoffset < 0) { + fprintf(stderr, "Can't specify a negative device offset `%d'\n", + mtdoffset); + exit (EXIT_FAILURE); + } + + argc -= optind; + argv += optind; + + /* + * There must be at least the MTD device node positional + * argument remaining and, optionally, the input file. + */ + + if (argc < 1 || argc > 2 || error) display_help (); - mtd_device = argv[optind++]; - img = argv[optind]; + mtd_device = argv[0]; + + /* + * Standard input may be specified either explictly as "-" or + * implicity by simply omitting the second of the two + * positional arguments. + */ + + img = ((argc == 2) ? argv[1] : standard_input); +} + +static void erase_buffer(void *buffer, size_t size) +{ + const uint8_t kEraseByte = 0xff; + + if (buffer != NULL && size > 0) { + memset(buffer, kEraseByte, size); + } } /* @@ -215,8 +248,12 @@ static void process_options (int argc, char * const argv[]) */ int main(int argc, char * const argv[]) { - int cnt, fd, ifd, imglen = 0, pagelen, blockstart = -1; + 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; @@ -226,7 +263,7 @@ int main(int argc, char * const argv[]) process_options(argc, argv); - memset(oobbuf, 0xff, sizeof(oobbuf)); + erase_buffer(oobbuf, sizeof(oobbuf)); if (pad && writeoob) { fprintf(stderr, "Can't pad when oob data is present.\n"); @@ -340,21 +377,48 @@ int main(int argc, char * const argv[]) oob.length = meminfo.oobsize; oob.ptr = noecc ? oobreadbuf : oobbuf; - /* Open the input file */ - if ((ifd = open(img, O_RDONLY)) == -1) { + /* 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; } - // get image length - imglen = lseek(ifd, 0, SEEK_END); - lseek (ifd, 0, SEEK_SET); + /* 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); - // Check, if file is pagealigned + /* + * 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 + * + */ + + 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\n"); + fprintf (stderr, "Input file is not page-aligned. Use the padding " + "option.\n"); goto closeall; } @@ -366,7 +430,13 @@ int main(int argc, char * const argv[]) goto closeall; } - /* Get data from input and write to the device */ + /* + * 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 @@ -379,7 +449,8 @@ int main(int argc, char * const argv[]) offs = blockstart; baderaseblock = false; if (!quiet) - fprintf (stdout, "Writing data to block %x\n", blockstart); + 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 { @@ -404,18 +475,50 @@ int main(int argc, char * const argv[]) } readlen = meminfo.writesize; - if (pad && (imglen < readlen)) - { - readlen = imglen; - memset(writebuf + readlen, 0xff, meminfo.writesize - readlen); - } - /* Read Page Data from input file */ - if ((cnt = read(ifd, writebuf, readlen)) != readlen) { - if (cnt == 0) // EOF + if (ifd != STDIN_FILENO) { + if (pad && (imglen < readlen)) + { + readlen = imglen; + erase_buffer(writebuf + readlen, meminfo.writesize - readlen); + } + + /* Read Page Data from input file */ + if ((cnt = read(ifd, writebuf, readlen)) != readlen) { + if (cnt == 0) // EOF + break; + perror ("File I/O error on input file"); + goto closeall; + } + } 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; - perror ("File I/O error on input file"); - goto closeall; + } + + /* 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) { @@ -499,7 +602,9 @@ int main(int argc, char * const argv[]) continue; } - imglen -= readlen; + if (ifd != STDIN_FILENO) { + imglen -= readlen; + } mtdoffset += meminfo.writesize; } @@ -517,7 +622,7 @@ restoreoob: close(fd); - if (imglen > 0) { + if ((ifd != STDIN_FILENO) && (imglen > 0)) { perror ("Data was only partially written due to error\n"); exit (EXIT_FAILURE); }