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/nand_write.c 330449 2018-03-05 07:26:05Z eadler $"); 31 32#include <stdio.h> 33#include <stdlib.h> 34#include <unistd.h> 35#include <fcntl.h> 36#include <libgeom.h> 37#include <sys/disk.h> 38#include <dev/nand/nand_dev.h> 39#include "nandtool.h" 40 41int nand_write(struct cmd_param *params) 42{ 43 struct chip_param_io chip_params; 44 char *dev, *file; 45 int in_fd = -1, ret = 0, done = 0; 46 int fd, block_size, mult, pos, count; 47 uint8_t *buf = NULL; 48 49 if (!(dev = param_get_string(params, "dev"))) { 50 fprintf(stderr, "Please supply 'dev' argument.\n"); 51 return (1); 52 } 53 54 if (!(file = param_get_string(params, "in"))) { 55 fprintf(stderr, "Please supply 'in' argument.\n"); 56 return (1); 57 } 58 59 if ((fd = g_open(dev, 1)) == -1) { 60 perrorf("Cannot open %s", dev); 61 return (1); 62 } 63 64 if ((in_fd = open(file, O_RDONLY)) == -1) { 65 perrorf("Cannot open file %s", file); 66 ret = 1; 67 goto out; 68 } 69 70 if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) { 71 perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)"); 72 ret = 1; 73 goto out; 74 } 75 76 block_size = chip_params.page_size * chip_params.pages_per_block; 77 78 if (param_has_value(params, "page")) { 79 pos = chip_params.page_size * param_get_int(params, "page"); 80 mult = chip_params.page_size; 81 } else if (param_has_value(params, "block")) { 82 pos = block_size * param_get_int(params, "block"); 83 mult = block_size; 84 } else if (param_has_value(params, "pos")) { 85 pos = param_get_int(params, "pos"); 86 mult = 1; 87 if (pos % chip_params.page_size) { 88 fprintf(stderr, "Position must be page-size " 89 "aligned!\n"); 90 ret = 1; 91 goto out; 92 } 93 } else { 94 fprintf(stderr, "You must specify one of: 'block', 'page'," 95 "'pos' arguments\n"); 96 ret = 1; 97 goto out; 98 } 99 100 if (!(param_has_value(params, "count"))) 101 count = mult; 102 else 103 count = param_get_int(params, "count") * mult; 104 105 if (!(buf = malloc(chip_params.page_size))) { 106 perrorf("Cannot allocate buffer [size %x]", 107 chip_params.page_size); 108 ret = 1; 109 goto out; 110 } 111 112 lseek(fd, pos, SEEK_SET); 113 114 while (done < count) { 115 if ((ret = read(in_fd, buf, chip_params.page_size)) != 116 (int32_t)chip_params.page_size) { 117 if (ret > 0) { 118 /* End of file ahead, truncate here */ 119 break; 120 } else { 121 perrorf("Cannot read from %s", file); 122 ret = 1; 123 goto out; 124 } 125 } 126 127 if ((ret = write(fd, buf, chip_params.page_size)) != 128 (int32_t)chip_params.page_size) { 129 ret = 1; 130 goto out; 131 } 132 133 done += ret; 134 } 135 136out: 137 g_close(fd); 138 if (in_fd != -1) 139 close(in_fd); 140 if (buf) 141 free(buf); 142 143 return (ret); 144} 145 146