nandtool.c revision 330449
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: stable/11/usr.sbin/nandtool/nandtool.c 330449 2018-03-05 07:26:05Z eadler $");
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
43int usage(struct cmd_param *);
44
45static 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
60static char *
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
77char *
78param_get_string(struct cmd_param *params, const char *name)
79{
80
81	return (_param_get_stringx(params, name, 0));
82}
83
84static int
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
106int
107param_get_intx(struct cmd_param *params, const char *name)
108{
109
110	return (_param_get_intx(params, name, 1));
111}
112
113int
114param_get_int(struct cmd_param *params, const char *name)
115{
116
117	return (_param_get_intx(params, name, 0));
118}
119
120int
121param_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
134int
135param_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
147int
148param_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
157void
158hexdumpoffset(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
179void
180hexdump(uint8_t *buf, int length)
181{
182
183	hexdumpoffset(buf, length, 0);
184}
185
186void *
187xmalloc(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
200void
201perrorf(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
211int
212usage(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
246int
247main(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