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