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