]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/nandtool/nandtool.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / nandtool / nandtool.c
1 /*-
2  * Copyright (c) 2010-2012 Semihalf.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <errno.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdarg.h>
35 #include <ctype.h>
36 #include <sysexits.h>
37 #include <libgeom.h>
38 #include "nandtool.h"
39 #include "usage.h"
40
41 int usage(struct cmd_param *);
42
43 static const struct {
44         const char      *name;
45         const char      *usage;
46         int             (*handler)(struct cmd_param *);
47 } commands[] = {
48         { "help", nand_help_usage, usage },
49         { "read", nand_read_usage, nand_read },
50         { "write", nand_write_usage, nand_write },
51         { "erase", nand_erase_usage, nand_erase },
52         { "readoob", nand_read_oob_usage, nand_read_oob },
53         { "writeoob", nand_write_oob_usage, nand_write_oob },
54         { "info", nand_info_usage, nand_info },
55         { NULL, NULL, NULL },
56 };
57
58 static char *
59 _param_get_stringx(struct cmd_param *params, const char *name, int doexit)
60 {
61         int i;
62
63         for (i = 0; params[i].name[0] != '\0'; i++) {
64                 if (!strcmp(params[i].name, name))
65                         return params[i].value;
66         }
67
68         if (doexit) {
69                 perrorf("Missing parameter %s", name);
70                 exit(1);
71         }
72         return (NULL);
73 }
74
75 char *
76 param_get_string(struct cmd_param *params, const char *name)
77 {
78
79         return (_param_get_stringx(params, name, 0));
80 }
81
82 static int
83 _param_get_intx(struct cmd_param *params, const char *name, int doexit)
84 {
85         int ret;
86         char *str = _param_get_stringx(params, name, doexit);
87
88         if (!str)
89                 return (-1);
90
91         errno = 0;
92         ret = (int)strtol(str, (char **)NULL, 10);
93         if (errno) {
94                 if (doexit) {
95                         perrorf("Invalid value for parameter %s", name);
96                         exit(1);
97                 }
98                 return (-1);
99         }
100
101         return (ret);
102 }
103
104 int
105 param_get_intx(struct cmd_param *params, const char *name)
106 {
107
108         return (_param_get_intx(params, name, 1));
109 }
110
111 int
112 param_get_int(struct cmd_param *params, const char *name)
113 {
114
115         return (_param_get_intx(params, name, 0));
116 }
117
118 int
119 param_get_boolean(struct cmd_param *params, const char *name)
120 {
121         char *str = param_get_string(params, name);
122
123         if (!str)
124                 return (0);
125
126         if (!strcmp(str, "true") || !strcmp(str, "yes"))
127                 return (1);
128
129         return (0);
130 }
131
132 int
133 param_has_value(struct cmd_param *params, const char *name)
134 {
135         int i;
136
137         for (i = 0; params[i].name[0] != '\0'; i++) {
138                 if (!strcmp(params[i].name, name))
139                         return (1);
140         }
141
142         return (0);
143 }
144
145 int
146 param_get_count(struct cmd_param *params)
147 {
148         int i;
149
150         for (i = 0; params[i].name[0] != '\0'; i++);
151
152         return (i);
153 }
154
155 void
156 hexdumpoffset(uint8_t *buf, int length, int off)
157 {
158         int i, j;
159         for (i = 0; i < length; i += 16) {
160                 printf("%08x: ", off + i);
161
162                 for (j = 0; j < 16; j++)
163                         printf("%02x ", buf[i+j]);
164
165                 printf("| ");
166
167                 for (j = 0; j < 16; j++) {
168                         printf("%c", isalnum(buf[i+j])
169                             ? buf[i+j]
170                             : '.');
171                 }
172
173                 printf("\n");
174         }
175 }
176
177 void
178 hexdump(uint8_t *buf, int length)
179 {
180
181         hexdumpoffset(buf, length, 0);
182 }
183
184 void *
185 xmalloc(size_t len)
186 {
187         void *ret = malloc(len);
188
189         if (!ret) {
190                 fprintf(stderr, "Cannot allocate buffer of %zd bytes. "
191                     "Exiting.\n", len);
192                 exit(EX_OSERR);
193         }
194
195         return (ret);
196 }
197
198 void
199 perrorf(const char *format, ...)
200 {
201         va_list args;
202
203         va_start(args, format);
204         vfprintf(stderr, format, args);
205         va_end(args);
206         fprintf(stderr, ": %s\n", strerror(errno));
207 }
208
209 int
210 usage(struct cmd_param *params)
211 {
212         int i;
213
214         if (!params || !param_get_count(params)) {
215                 fprintf(stderr, "Usage: nandtool <command> [arguments...]\n");
216                 fprintf(stderr, "Arguments are in form 'name=value'.\n\n");
217                 fprintf(stderr, "Available commands:\n");
218
219                 for (i = 0; commands[i].name != NULL; i++)
220                         fprintf(stderr, "\t%s\n", commands[i].name);
221
222                 fprintf(stderr, "\n");
223                 fprintf(stderr, "For information about particular command, "
224                     "type:\n");
225                 fprintf(stderr, "'nandtool help topic=<command>'\n");
226         } else if (param_has_value(params, "topic")) {
227                 for (i = 0; commands[i].name != NULL; i++) {
228                         if (!strcmp(param_get_string(params, "topic"),
229                             commands[i].name)) {
230                                 fprintf(stderr, commands[i].usage, "nandtool");
231                                 return (0);
232                         }
233                 }
234
235                 fprintf(stderr, "No such command\n");
236                 return (EX_SOFTWARE);
237         } else {
238                 fprintf(stderr, "Wrong arguments given. Try: 'nandtool help'\n");
239         }
240
241         return (EX_USAGE);
242 }
243
244 int
245 main(int argc, const char *argv[])
246 {
247         struct cmd_param *params;
248         int i, ret, idx;
249
250         if (argc < 2) {
251                 usage(NULL);
252                 return (0);
253         }
254
255         params = malloc(sizeof(struct cmd_param) * (argc - 1));
256
257         for (i = 2, idx = 0; i < argc; i++, idx++) {
258                 if (sscanf(argv[i], "%63[^=]=%63s", params[idx].name,
259                     params[idx].value) < 2) {
260                         fprintf(stderr, "Syntax error in argument %d. "
261                             "Argument should be in form 'name=value'.\n", i);
262                         free(params);
263                         return (-1);
264                 }
265         }
266
267         params[idx].name[0] = '\0';
268         params[idx].value[0] = '\0';
269
270         for (i = 0; commands[i].name != NULL; i++) {
271                 if (!strcmp(commands[i].name, argv[1])) {
272                         ret = commands[i].handler(params);
273                         free(params);
274                         return (ret);
275                 }
276         }
277
278         free(params);
279         fprintf(stderr, "Unknown command. Try '%s help'\n", argv[0]);
280
281         return (-1);
282 }
283