1235537Sgber/*- 2235537Sgber * Copyright (c) 2010-2012 Semihalf. 3235537Sgber * All rights reserved. 4235537Sgber * 5235537Sgber * Redistribution and use in source and binary forms, with or without 6235537Sgber * modification, are permitted provided that the following conditions 7235537Sgber * are met: 8235537Sgber * 1. Redistributions of source code must retain the above copyright 9235537Sgber * notice, this list of conditions and the following disclaimer. 10235537Sgber * 2. Redistributions in binary form must reproduce the above copyright 11235537Sgber * notice, this list of conditions and the following disclaimer in the 12235537Sgber * documentation and/or other materials provided with the distribution. 13235537Sgber * 14235537Sgber * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15235537Sgber * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16235537Sgber * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17235537Sgber * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18235537Sgber * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19235537Sgber * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20235537Sgber * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21235537Sgber * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22235537Sgber * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23235537Sgber * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24235537Sgber * SUCH DAMAGE. 25235537Sgber */ 26235537Sgber 27235537Sgber#include <sys/cdefs.h> 28235537Sgber__FBSDID("$FreeBSD$"); 29235537Sgber 30235537Sgber#include <errno.h> 31235537Sgber#include <stdio.h> 32235537Sgber#include <stdlib.h> 33235537Sgber#include <string.h> 34235537Sgber#include <stdarg.h> 35235537Sgber#include <ctype.h> 36235537Sgber#include <sysexits.h> 37235537Sgber#include <libgeom.h> 38235537Sgber#include "nandtool.h" 39235537Sgber#include "usage.h" 40235537Sgber 41235537Sgberint usage(struct cmd_param *); 42235537Sgber 43235537Sgberstatic const struct { 44235537Sgber const char *name; 45235537Sgber const char *usage; 46235537Sgber int (*handler)(struct cmd_param *); 47235537Sgber} commands[] = { 48235537Sgber { "help", nand_help_usage, usage }, 49235537Sgber { "read", nand_read_usage, nand_read }, 50235537Sgber { "write", nand_write_usage, nand_write }, 51235537Sgber { "erase", nand_erase_usage, nand_erase }, 52235537Sgber { "readoob", nand_read_oob_usage, nand_read_oob }, 53235537Sgber { "writeoob", nand_write_oob_usage, nand_write_oob }, 54235537Sgber { "info", nand_info_usage, nand_info }, 55235537Sgber { NULL, NULL, NULL }, 56235537Sgber}; 57235537Sgber 58235537Sgberstatic char * 59235537Sgber_param_get_stringx(struct cmd_param *params, const char *name, int doexit) 60235537Sgber{ 61235537Sgber int i; 62235537Sgber 63235537Sgber for (i = 0; params[i].name[0] != '\0'; i++) { 64235537Sgber if (!strcmp(params[i].name, name)) 65235537Sgber return params[i].value; 66235537Sgber } 67235537Sgber 68235537Sgber if (doexit) { 69235537Sgber perrorf("Missing parameter %s", name); 70235537Sgber exit(1); 71235537Sgber } 72235537Sgber return (NULL); 73235537Sgber} 74235537Sgber 75235537Sgberchar * 76235537Sgberparam_get_string(struct cmd_param *params, const char *name) 77235537Sgber{ 78235537Sgber 79235537Sgber return (_param_get_stringx(params, name, 0)); 80235537Sgber} 81235537Sgber 82235537Sgberstatic int 83235537Sgber_param_get_intx(struct cmd_param *params, const char *name, int doexit) 84235537Sgber{ 85235537Sgber int ret; 86235537Sgber char *str = _param_get_stringx(params, name, doexit); 87235537Sgber 88235537Sgber if (!str) 89235537Sgber return (-1); 90235537Sgber 91235537Sgber errno = 0; 92235537Sgber ret = (int)strtol(str, (char **)NULL, 10); 93235537Sgber if (errno) { 94235537Sgber if (doexit) { 95235537Sgber perrorf("Invalid value for parameter %s", name); 96235537Sgber exit(1); 97235537Sgber } 98235537Sgber return (-1); 99235537Sgber } 100235537Sgber 101235537Sgber return (ret); 102235537Sgber} 103235537Sgber 104235537Sgberint 105235537Sgberparam_get_intx(struct cmd_param *params, const char *name) 106235537Sgber{ 107235537Sgber 108235537Sgber return (_param_get_intx(params, name, 1)); 109235537Sgber} 110235537Sgber 111235537Sgberint 112235537Sgberparam_get_int(struct cmd_param *params, const char *name) 113235537Sgber{ 114235537Sgber 115235537Sgber return (_param_get_intx(params, name, 0)); 116235537Sgber} 117235537Sgber 118235537Sgberint 119235537Sgberparam_get_boolean(struct cmd_param *params, const char *name) 120235537Sgber{ 121235537Sgber char *str = param_get_string(params, name); 122235537Sgber 123235537Sgber if (!str) 124235537Sgber return (0); 125235537Sgber 126235537Sgber if (!strcmp(str, "true") || !strcmp(str, "yes")) 127235537Sgber return (1); 128235537Sgber 129235537Sgber return (0); 130235537Sgber} 131235537Sgber 132235537Sgberint 133235537Sgberparam_has_value(struct cmd_param *params, const char *name) 134235537Sgber{ 135235537Sgber int i; 136235537Sgber 137235537Sgber for (i = 0; params[i].name[0] != '\0'; i++) { 138235537Sgber if (!strcmp(params[i].name, name)) 139235537Sgber return (1); 140235537Sgber } 141235537Sgber 142235537Sgber return (0); 143235537Sgber} 144235537Sgber 145235537Sgberint 146235537Sgberparam_get_count(struct cmd_param *params) 147235537Sgber{ 148235537Sgber int i; 149235537Sgber 150235537Sgber for (i = 0; params[i].name[0] != '\0'; i++); 151235537Sgber 152235537Sgber return (i); 153235537Sgber} 154235537Sgber 155235537Sgbervoid 156235537Sgberhexdumpoffset(uint8_t *buf, int length, int off) 157235537Sgber{ 158235537Sgber int i, j; 159235537Sgber for (i = 0; i < length; i += 16) { 160235537Sgber printf("%08x: ", off + i); 161235537Sgber 162235537Sgber for (j = 0; j < 16; j++) 163235537Sgber printf("%02x ", buf[i+j]); 164235537Sgber 165235537Sgber printf("| "); 166235537Sgber 167235537Sgber for (j = 0; j < 16; j++) { 168235537Sgber printf("%c", isalnum(buf[i+j]) 169235537Sgber ? buf[i+j] 170235537Sgber : '.'); 171235537Sgber } 172235537Sgber 173235537Sgber printf("\n"); 174235537Sgber } 175235537Sgber} 176235537Sgber 177235537Sgbervoid 178235537Sgberhexdump(uint8_t *buf, int length) 179235537Sgber{ 180235537Sgber 181235537Sgber hexdumpoffset(buf, length, 0); 182235537Sgber} 183235537Sgber 184235537Sgbervoid * 185235537Sgberxmalloc(size_t len) 186235537Sgber{ 187235537Sgber void *ret = malloc(len); 188235537Sgber 189235537Sgber if (!ret) { 190235537Sgber fprintf(stderr, "Cannot allocate buffer of %zd bytes. " 191235537Sgber "Exiting.\n", len); 192235537Sgber exit(EX_OSERR); 193235537Sgber } 194235537Sgber 195235537Sgber return (ret); 196235537Sgber} 197235537Sgber 198235537Sgbervoid 199235537Sgberperrorf(const char *format, ...) 200235537Sgber{ 201235537Sgber va_list args; 202235537Sgber 203235537Sgber va_start(args, format); 204235537Sgber vfprintf(stderr, format, args); 205235537Sgber va_end(args); 206235537Sgber fprintf(stderr, ": %s\n", strerror(errno)); 207235537Sgber} 208235537Sgber 209235537Sgberint 210235537Sgberusage(struct cmd_param *params) 211235537Sgber{ 212235537Sgber int i; 213235537Sgber 214235537Sgber if (!params || !param_get_count(params)) { 215235537Sgber fprintf(stderr, "Usage: nandtool <command> [arguments...]\n"); 216235537Sgber fprintf(stderr, "Arguments are in form 'name=value'.\n\n"); 217235537Sgber fprintf(stderr, "Available commands:\n"); 218235537Sgber 219235537Sgber for (i = 0; commands[i].name != NULL; i++) 220235537Sgber fprintf(stderr, "\t%s\n", commands[i].name); 221235537Sgber 222235537Sgber fprintf(stderr, "\n"); 223235537Sgber fprintf(stderr, "For information about particular command, " 224235537Sgber "type:\n"); 225235537Sgber fprintf(stderr, "'nandtool help topic=<command>'\n"); 226235537Sgber } else if (param_has_value(params, "topic")) { 227235537Sgber for (i = 0; commands[i].name != NULL; i++) { 228235537Sgber if (!strcmp(param_get_string(params, "topic"), 229235537Sgber commands[i].name)) { 230235537Sgber fprintf(stderr, commands[i].usage, "nandtool"); 231235537Sgber return (0); 232235537Sgber } 233235537Sgber } 234235537Sgber 235235537Sgber fprintf(stderr, "No such command\n"); 236235537Sgber return (EX_SOFTWARE); 237235537Sgber } else { 238235537Sgber fprintf(stderr, "Wrong arguments given. Try: 'nandtool help'\n"); 239235537Sgber } 240235537Sgber 241235537Sgber return (EX_USAGE); 242235537Sgber} 243235537Sgber 244235537Sgberint 245235537Sgbermain(int argc, const char *argv[]) 246235537Sgber{ 247235537Sgber struct cmd_param *params; 248235537Sgber int i, ret, idx; 249235537Sgber 250235537Sgber if (argc < 2) { 251235537Sgber usage(NULL); 252235537Sgber return (0); 253235537Sgber } 254235537Sgber 255235537Sgber params = malloc(sizeof(struct cmd_param) * (argc - 1)); 256235537Sgber 257235537Sgber for (i = 2, idx = 0; i < argc; i++, idx++) { 258235537Sgber if (sscanf(argv[i], "%63[^=]=%63s", params[idx].name, 259235537Sgber params[idx].value) < 2) { 260235537Sgber fprintf(stderr, "Syntax error in argument %d. " 261235537Sgber "Argument should be in form 'name=value'.\n", i); 262235537Sgber free(params); 263235537Sgber return (-1); 264235537Sgber } 265235537Sgber } 266235537Sgber 267235537Sgber params[idx].name[0] = '\0'; 268235537Sgber params[idx].value[0] = '\0'; 269235537Sgber 270235537Sgber for (i = 0; commands[i].name != NULL; i++) { 271235537Sgber if (!strcmp(commands[i].name, argv[1])) { 272235537Sgber ret = commands[i].handler(params); 273235537Sgber free(params); 274235537Sgber return (ret); 275235537Sgber } 276235537Sgber } 277235537Sgber 278235537Sgber free(params); 279235537Sgber fprintf(stderr, "Unknown command. Try '%s help'\n", argv[0]); 280235537Sgber 281235537Sgber return (-1); 282235537Sgber} 283235537Sgber 284