source: MondoRescue/branches/3.3/mindi-busybox/miscutils/flashcp.c@ 3647

Last change on this file since 3647 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 4.0 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/* If 1, simulates "flashing" by writing to existing regular file */
20#define MTD_DEBUG 0
21
22#define OPT_v (1 << 0)
23
24#define BUFSIZE (4 * 1024)
25
26static void progress(int mode, uoff_t count, uoff_t total)
27{
28 uoff_t percent;
29
30 if (!option_mask32) //if (!(option_mask32 & OPT_v))
31 return;
32 percent = count * 100;
33 if (total)
34 percent = (unsigned) (percent / total);
35 printf("\r%s: %"OFF_FMT"u/%"OFF_FMT"u (%u%%) ",
36 (mode < 0) ? "Erasing block" : ((mode == 0) ? "Writing kb" : "Verifying kb"),
37 count, total, (unsigned)percent);
38 fflush_all();
39}
40
41static void progress_newline(void)
42{
43 if (!option_mask32) //if (!(option_mask32 & OPT_v))
44 return;
45 bb_putchar('\n');
46}
47
48int flashcp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
49int flashcp_main(int argc UNUSED_PARAM, char **argv)
50{
51 int fd_f, fd_d; /* input file and mtd device file descriptors */
52 int i;
53 uoff_t erase_count;
54 struct mtd_info_user mtd;
55 struct erase_info_user e;
56 struct stat statb;
57// const char *filename, *devicename;
58 RESERVE_CONFIG_UBUFFER(buf, BUFSIZE);
59 RESERVE_CONFIG_UBUFFER(buf2, BUFSIZE);
60
61 opt_complementary = "=2"; /* exactly 2 non-option args: file, dev */
62 /*opts =*/ getopt32(argv, "v");
63 argv += optind;
64// filename = *argv++;
65// devicename = *argv;
66#define filename argv[0]
67#define devicename argv[1]
68
69 /* open input file and mtd device and do sanity checks */
70 fd_f = xopen(filename, O_RDONLY);
71 fstat(fd_f, &statb);
72 fd_d = xopen(devicename, O_SYNC | O_RDWR);
73#if !MTD_DEBUG
74 if (ioctl(fd_d, MEMGETINFO, &mtd) < 0) {
75 bb_error_msg_and_die("%s is not a MTD flash device", devicename);
76 }
77 if (statb.st_size > mtd.size) {
78 bb_error_msg_and_die("%s bigger than %s", filename, devicename);
79 }
80#else
81 mtd.erasesize = 64 * 1024;
82#endif
83
84 /* always erase a complete block */
85 erase_count = (uoff_t)(statb.st_size + mtd.erasesize - 1) / mtd.erasesize;
86 /* erase 1 block at a time to be able to give verbose output */
87 e.length = mtd.erasesize;
88#if 0
89/* (1) bloat
90 * (2) will it work for multi-gigabyte devices?
91 * (3) worse wrt error detection granularity
92 */
93 /* optimization: if not verbose, erase in one go */
94 if (!opts) { // if (!(opts & OPT_v))
95 e.length = mtd.erasesize * erase_count;
96 erase_count = 1;
97 }
98#endif
99 e.start = 0;
100 for (i = 1; i <= erase_count; i++) {
101 progress(-1, i, erase_count);
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 = 0; i <= 1; 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;
126
127 progress(i, done / 1024, (uoff_t)statb.st_size / 1024);
128 rem = statb.st_size - done;
129 if (rem == 0)
130 break;
131 if (rem < BUFSIZE)
132 count = rem;
133 xread(fd_f, buf, count);
134 if (i == 0) {
135 int ret;
136 if (count < BUFSIZE)
137 memset((char*)buf + count, 0, BUFSIZE - count);
138 errno = 0;
139 ret = full_write(fd_d, buf, BUFSIZE);
140 if (ret != BUFSIZE) {
141 bb_perror_msg_and_die("write error at 0x%"OFF_FMT"x on %s, "
142 "write returned %d",
143 done, devicename, ret);
144 }
145 } else { /* i == 1 */
146 xread(fd_d, buf2, count);
147 if (memcmp(buf, buf2, count) != 0) {
148 bb_error_msg_and_die("verification mismatch at 0x%"OFF_FMT"x", done);
149 }
150 }
151
152 done += count;
153 }
154
155 progress_newline();
156 }
157 /* we won't come here if there was an error */
158
159 return EXIT_SUCCESS;
160}
Note: See TracBrowser for help on using the repository browser.