source: branches/3.2/mindi-busybox/miscutils/flashcp.c @ 3232

Last change on this file since 3232 was 3232, checked in by Bruno Cornec, 7 years ago
  • Update mindi-busybox to 1.21.1
  • Property svn:eol-style set to native
File size: 3.8 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * busybox reimplementation of flashcp
4 *
5 * (C) 2009 Stefan Seyfried <seife@sphairon.com>
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9
10//usage:#define flashcp_trivial_usage
11//usage:       "-v FILE MTD_DEVICE"
12//usage:#define flashcp_full_usage "\n\n"
13//usage:       "Copy an image to MTD device\n"
14//usage:     "\n    -v  Verbose"
15
16#include "libbb.h"
17#include <mtd/mtd-user.h>
18
19#define MTD_DEBUG 0
20
21#define OPT_v (1 << 0)
22
23#define BUFSIZE (8 * 1024)
24
25static void progress(int mode, uoff_t count, uoff_t total)
26{
27    uoff_t percent;
28
29    if (!option_mask32) //if (!(option_mask32 & OPT_v))
30        return;
31    percent = count * 100;
32    if (total)
33        percent = (unsigned) (percent / total);
34    printf("\r%s: %"OFF_FMT"u/%"OFF_FMT"u (%u%%) ",
35        (mode == 0) ? "Erasing block" : ((mode == 1) ? "Writing kb" : "Verifying kb"),
36        count, total, (unsigned)percent);
37    fflush_all();
38}
39
40static void progress_newline(void)
41{
42    if (!option_mask32) //if (!(option_mask32 & OPT_v))
43        return;
44    bb_putchar('\n');
45}
46
47int flashcp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
48int flashcp_main(int argc UNUSED_PARAM, char **argv)
49{
50    int fd_f, fd_d; /* input file and mtd device file descriptors */
51    int i;
52    uoff_t erase_count;
53    struct mtd_info_user mtd;
54    struct erase_info_user e;
55    struct stat statb;
56//  const char *filename, *devicename;
57    RESERVE_CONFIG_UBUFFER(buf, BUFSIZE);
58    RESERVE_CONFIG_UBUFFER(buf2, BUFSIZE);
59
60    opt_complementary = "=2"; /* exactly 2 non-option args: file, dev */
61    /*opts =*/ getopt32(argv, "v");
62    argv += optind;
63//  filename = *argv++;
64//  devicename = *argv;
65#define filename argv[0]
66#define devicename argv[1]
67
68    /* open input file and mtd device and do sanity checks */
69    fd_f = xopen(filename, O_RDONLY);
70    fstat(fd_f, &statb);
71    fd_d = xopen(devicename, O_SYNC | O_RDWR);
72#if !MTD_DEBUG
73    if (ioctl(fd_d, MEMGETINFO, &mtd) < 0) {
74        bb_error_msg_and_die("%s is not a MTD flash device", devicename);
75    }
76    if (statb.st_size > mtd.size) {
77        bb_error_msg_and_die("%s bigger than %s", filename, devicename);
78    }
79#else
80    mtd.erasesize = 64 * 1024;
81#endif
82
83    /* always erase a complete block */
84    erase_count = (uoff_t)(statb.st_size + mtd.erasesize - 1) / mtd.erasesize;
85    /* erase 1 block at a time to be able to give verbose output */
86    e.length = mtd.erasesize;
87#if 0
88/* (1) bloat
89 * (2) will it work for multi-gigabyte devices?
90 * (3) worse wrt error detection granularity
91 */
92    /* optimization: if not verbose, erase in one go */
93    if (!opts) { // if (!(opts & OPT_v))
94        e.length = mtd.erasesize * erase_count;
95        erase_count = 1;
96    }
97#endif
98    e.start = 0;
99    for (i = 1; i <= erase_count; i++) {
100        progress(0, i, erase_count);
101        errno = 0;
102#if !MTD_DEBUG
103        if (ioctl(fd_d, MEMERASE, &e) < 0) {
104            bb_perror_msg_and_die("erase error at 0x%llx on %s",
105                (long long)e.start, devicename);
106        }
107#else
108        usleep(100*1000);
109#endif
110        e.start += mtd.erasesize;
111    }
112    progress_newline();
113
114    /* doing this outer loop gives significantly smaller code
115     * than doing two separate loops for writing and verifying */
116    for (i = 1; i <= 2; i++) {
117        uoff_t done;
118        unsigned count;
119
120        xlseek(fd_f, 0, SEEK_SET);
121        xlseek(fd_d, 0, SEEK_SET);
122        done = 0;
123        count = BUFSIZE;
124        while (1) {
125            uoff_t rem = statb.st_size - done;
126            if (rem == 0)
127                break;
128            if (rem < BUFSIZE)
129                count = rem;
130            progress(i, done / 1024, (uoff_t)statb.st_size / 1024);
131            xread(fd_f, buf, count);
132            if (i == 1) {
133                int ret;
134                errno = 0;
135                ret = full_write(fd_d, buf, count);
136                if (ret != count) {
137                    bb_perror_msg_and_die("write error at 0x%"OFF_FMT"x on %s, "
138                        "write returned %d",
139                        done, devicename, ret);
140                }
141            } else { /* i == 2 */
142                xread(fd_d, buf2, count);
143                if (memcmp(buf, buf2, count)) {
144                    bb_error_msg_and_die("verification mismatch at 0x%"OFF_FMT"x", done);
145                }
146            }
147
148            done += count;
149        }
150
151        progress_newline();
152    }
153    /* we won't come here if there was an error */
154
155    return EXIT_SUCCESS;
156}
Note: See TracBrowser for help on using the repository browser.