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: releng/11.0/usr.sbin/nandtool/nandtool.c 235537 2012-05-17 10:11:18Z gber $"); 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 41int usage(struct cmd_param *); 42 43static 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 58static 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 75char * 76param_get_string(struct cmd_param *params, const char *name) 77{ 78 79 return (_param_get_stringx(params, name, 0)); 80} 81 82static 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 104int 105param_get_intx(struct cmd_param *params, const char *name) 106{ 107 108 return (_param_get_intx(params, name, 1)); 109} 110 111int 112param_get_int(struct cmd_param *params, const char *name) 113{ 114 115 return (_param_get_intx(params, name, 0)); 116} 117 118int 119param_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 132int 133param_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 145int 146param_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 155void 156hexdumpoffset(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 177void 178hexdump(uint8_t *buf, int length) 179{ 180 181 hexdumpoffset(buf, length, 0); 182} 183 184void * 185xmalloc(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 198void 199perrorf(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 209int 210usage(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 244int 245main(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 284