1169689Skan/*- 2169689Skan * Copyright (c) 2010-2012 Semihalf. 3169689Skan * All rights reserved. 4169689Skan * 5169689Skan * Redistribution and use in source and binary forms, with or without 6169689Skan * modification, are permitted provided that the following conditions 7169689Skan * are met: 8169689Skan * 1. Redistributions of source code must retain the above copyright 9169689Skan * notice, this list of conditions and the following disclaimer. 10169689Skan * 2. Redistributions in binary form must reproduce the above copyright 11169689Skan * notice, this list of conditions and the following disclaimer in the 12169689Skan * documentation and/or other materials provided with the distribution. 13169689Skan * 14169689Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24169689Skan * SUCH DAMAGE. 25169689Skan */ 26169689Skan 27169689Skan#include <sys/cdefs.h> 28169689Skan__FBSDID("$FreeBSD: releng/10.2/usr.sbin/nandtool/nand_read.c 235537 2012-05-17 10:11:18Z gber $"); 29169689Skan 30169689Skan#include <stdio.h> 31169689Skan#include <stdlib.h> 32169689Skan#include <unistd.h> 33169689Skan#include <fcntl.h> 34169689Skan#include <libgeom.h> 35169689Skan#include <sys/disk.h> 36169689Skan#include <dev/nand/nand_dev.h> 37169689Skan#include "nandtool.h" 38169689Skan 39169689Skanint nand_read(struct cmd_param *params) 40169689Skan{ 41169689Skan struct chip_param_io chip_params; 42169689Skan int fd = -1, out_fd = -1, done = 0, ret = 0; 43169689Skan char *dev, *out; 44169689Skan int pos, count, mult, block_size; 45169689Skan uint8_t *buf = NULL; 46169689Skan 47169689Skan if (!(dev = param_get_string(params, "dev"))) { 48169689Skan fprintf(stderr, "You must specify 'dev' parameter\n"); 49169689Skan return (1); 50169689Skan } 51169689Skan 52169689Skan if ((out = param_get_string(params, "out"))) { 53169689Skan out_fd = open(out, O_WRONLY|O_CREAT); 54169689Skan if (out_fd == -1) { 55169689Skan perrorf("Cannot open %s for writing", out); 56169689Skan return (1); 57169689Skan } 58169689Skan } 59169689Skan 60169689Skan if ((fd = g_open(dev, 1)) == -1) { 61169689Skan perrorf("Cannot open %s", dev); 62169689Skan ret = 1; 63169689Skan goto out; 64169689Skan } 65169689Skan 66169689Skan if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) { 67169689Skan perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)"); 68169689Skan ret = 1; 69169689Skan goto out; 70169689Skan } 71169689Skan 72169689Skan block_size = chip_params.page_size * chip_params.pages_per_block; 73169689Skan 74169689Skan if (param_has_value(params, "page")) { 75169689Skan pos = chip_params.page_size * param_get_int(params, "page"); 76169689Skan mult = chip_params.page_size; 77169689Skan } else if (param_has_value(params, "block")) { 78169689Skan pos = block_size * param_get_int(params, "block"); 79169689Skan mult = block_size; 80169689Skan } else if (param_has_value(params, "pos")) { 81169689Skan pos = param_get_int(params, "pos"); 82169689Skan mult = 1; 83169689Skan if (pos % chip_params.page_size) { 84169689Skan fprintf(stderr, "Position must be page-size aligned!\n"); 85169689Skan ret = 1; 86169689Skan goto out; 87169689Skan } 88169689Skan } else { 89169689Skan fprintf(stderr, "You must specify one of: 'block', 'page'," 90169689Skan "'pos' arguments\n"); 91169689Skan ret = 1; 92169689Skan goto out; 93169689Skan } 94169689Skan 95169689Skan if (!(param_has_value(params, "count"))) 96169689Skan count = mult; 97169689Skan else 98169689Skan count = param_get_int(params, "count") * mult; 99169689Skan 100169689Skan if (!(buf = malloc(chip_params.page_size))) { 101169689Skan perrorf("Cannot allocate buffer [size %x]", 102169689Skan chip_params.page_size); 103169689Skan ret = 1; 104169689Skan goto out; 105169689Skan } 106169689Skan 107169689Skan lseek(fd, pos, SEEK_SET); 108169689Skan 109169689Skan while (done < count) { 110169689Skan if ((ret = read(fd, buf, chip_params.page_size)) != 111169689Skan (int32_t)chip_params.page_size) { 112169689Skan perrorf("read error (read %d bytes)", ret); 113169689Skan goto out; 114169689Skan } 115169689Skan 116169689Skan if (out_fd != -1) { 117169689Skan done += ret; 118169689Skan if ((ret = write(out_fd, buf, chip_params.page_size)) != 119169689Skan (int32_t)chip_params.page_size) { 120169689Skan perrorf("write error (written %d bytes)", ret); 121169689Skan ret = 1; 122169689Skan goto out; 123169689Skan } 124169689Skan } else { 125169689Skan hexdumpoffset(buf, chip_params.page_size, done); 126169689Skan done += ret; 127169689Skan } 128169689Skan } 129169689Skan 130169689Skanout: 131169689Skan g_close(fd); 132169689Skan if (out_fd != -1) 133169689Skan close(out_fd); 134169689Skan if (buf) 135169689Skan free(buf); 136169689Skan 137169689Skan return (ret); 138169689Skan} 139169689Skan 140169689Skan