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

Last change on this file since 3232 was 3232, checked in by Bruno Cornec, 10 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.