1 /* 2 * Copyright (C) 2007 Nokia Corporation. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 as published by 6 * the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * this program; if not, write to the Free Software Foundation, Inc., 51 15 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 */ 17 18 /* 19 * An utility to delete UBI devices (detach MTD devices from UBI). 20 * 21 * Author: Artem Bityutskiy 22 */ 23 24 #define PROGRAM_NAME "ubidetach" 25 #define VERSION "owrt-fstools" 26 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <fcntl.h> 30 #include <stdio.h> 31 #include <stdint.h> 32 #include <getopt.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <unistd.h> 36 37 #include "libubi-tiny.h" 38 39 #define DEFAULT_CTRL_DEV "/dev/ubi_ctrl" 40 41 static int ubi_write(char *node, int fd, const void *buf, int len) 42 { 43 int ret; 44 45 while (len) { 46 ret = write(fd, buf, len); 47 if (ret < 0) { 48 if (errno == EINTR) { 49 fprintf(stderr, "do not interrupt me!"); 50 continue; 51 } 52 fprintf(stderr, "cannot write %d bytes to volume \"%s\"", len, node); 53 return -1; 54 } 55 56 if (ret == 0) { 57 fprintf(stderr, "cannot write %d bytes to volume \"%s\"", len, node); 58 return -1; 59 } 60 len -= ret; 61 buf += ret; 62 } 63 64 return 0; 65 } 66 67 static int update_volume(libubi_t libubi, struct ubi_vol_info *vol_info, char *node, char *img, int skip) 68 { 69 int err, fd, ifd; 70 long long bytes; 71 char *buf; 72 struct stat st; 73 74 buf = malloc(vol_info->leb_size); 75 if (!buf) { 76 fprintf(stderr, "cannot allocate %d bytes of memory", vol_info->leb_size); 77 return -1; 78 } 79 err = stat(img, &st); 80 if (err < 0) { 81 fprintf(stderr, "stat failed on \"%s\"", img); 82 goto out_free; 83 } 84 85 bytes = st.st_size - skip; 86 87 if (bytes > vol_info->rsvd_bytes) { 88 fprintf(stderr, "\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)", 89 img, bytes, node, vol_info->rsvd_bytes); 90 goto out_free; 91 } 92 93 fd = open(node, O_RDWR); 94 if (fd == -1) { 95 fprintf(stderr, "cannot open UBI volume \"%s\"", node); 96 goto out_free; 97 } 98 99 ifd = open(img, O_RDONLY); 100 if (ifd == -1) { 101 fprintf(stderr, "cannot open \"%s\"", img); 102 goto out_close1; 103 } 104 105 if (skip && lseek(ifd, skip, SEEK_CUR) == -1) { 106 fprintf(stderr, "lseek input by %d failed", skip); 107 goto out_close; 108 } 109 110 err = ubi_update_start(libubi, fd, bytes); 111 if (err) { 112 fprintf(stderr, "cannot start volume \"%s\" update", node); 113 goto out_close; 114 } 115 116 while (bytes) { 117 ssize_t ret; 118 int to_copy = vol_info->leb_size; 119 if (to_copy > bytes) 120 to_copy = bytes; 121 122 ret = read(ifd, buf, to_copy); 123 if (ret <= 0) { 124 if (errno == EINTR) { 125 fprintf(stderr, "do not interrupt me!"); 126 continue; 127 } else { 128 fprintf(stderr, "cannot read %d bytes from \"%s\"", 129 to_copy, img); 130 goto out_close; 131 } 132 } 133 134 err = ubi_write(node, fd, buf, ret); 135 if (err) 136 goto out_close; 137 bytes -= ret; 138 } 139 140 close(ifd); 141 close(fd); 142 free(buf); 143 return 0; 144 145 out_close: 146 close(ifd); 147 out_close1: 148 close(fd); 149 out_free: 150 free(buf); 151 return -1; 152 } 153 154 int ubiattach(libubi_t libubi, char *mtd) 155 { 156 struct ubi_attach_request req = { 157 .dev_num = UBI_DEV_NUM_AUTO, 158 .mtd_num = -1, 159 .vid_hdr_offset = 0, 160 .max_beb_per1024 = 0, 161 .mtd_dev_node = mtd, 162 }; 163 int err = ubi_attach(libubi, DEFAULT_CTRL_DEV, &req); 164 165 if (err) { 166 fprintf(stderr, "cannot attach \"%s\"", mtd); 167 return err; 168 } 169 170 return 0; 171 } 172 173 int ubidetach(libubi_t libubi, char *mtd) 174 { 175 return ubi_detach(libubi, DEFAULT_CTRL_DEV, mtd); 176 } 177 178 int ubirsvol(libubi_t libubi, char *node, char *name, int bytes) 179 { 180 struct ubi_dev_info dev_info; 181 struct ubi_vol_info vol_info; 182 int err = ubi_get_dev_info(libubi, node, &dev_info); 183 184 if (err) { 185 fprintf(stderr, "cannot get information about UBI device \"%s\"", 186 node); 187 return -1; 188 } 189 err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num, name, &vol_info); 190 if (err) { 191 fprintf(stderr, "cannot find UBI volume \"%s\"", name); 192 return -1; 193 } 194 195 err = ubi_rsvol(libubi, node, vol_info.vol_id, bytes); 196 if (err) { 197 fprintf(stderr, "cannot UBI resize volume"); 198 return -1; 199 } 200 201 return 0; 202 } 203 204 int ubirmvol(libubi_t libubi, char *node, char *name) 205 { 206 struct ubi_dev_info dev_info; 207 struct ubi_vol_info vol_info; 208 int err = ubi_get_dev_info(libubi, node, &dev_info); 209 210 if (err) { 211 fprintf(stderr, "cannot get information about UBI device \"%s\"", 212 node); 213 return -1; 214 } 215 216 err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num, name, &vol_info); 217 if (err) { 218 fprintf(stderr, "cannot find UBI volume \"%s\"", name); 219 return -1; 220 } 221 222 err = ubi_rmvol(libubi, node, vol_info.vol_id); 223 if (err) { 224 fprintf(stderr, "cannot UBI remove volume"); 225 return -1; 226 } 227 228 return 0; 229 } 230 231 int ubimkvol(libubi_t libubi, char *node, char *name, int maxavs) 232 { 233 struct ubi_dev_info dev_info; 234 struct ubi_vol_info vol_info; 235 struct ubi_mkvol_request req; 236 int err = ubi_get_dev_info(libubi, node, &dev_info); 237 238 if (err) { 239 fprintf(stderr, "cannot get information about UBI device \"%s\"", 240 node); 241 return -1; 242 } 243 244 if (dev_info.avail_bytes == 0) { 245 fprintf(stderr, "UBI device does not have free logical eraseblocks"); 246 return -1; 247 } 248 249 if (maxavs) 250 printf("Set volume size to %lld\n", dev_info.avail_bytes); 251 252 req.vol_id = UBI_VOL_NUM_AUTO; 253 req.alignment = 1; 254 req.bytes = dev_info.avail_bytes; 255 req.vol_type = UBI_DYNAMIC_VOLUME; 256 req.name = name; 257 258 err = ubi_mkvol(libubi, node, &req); 259 if (err < 0) { 260 fprintf(stderr, "cannot UBI create volume"); 261 return -1; 262 } 263 264 /* Print information about the created device */ 265 err = ubi_get_vol_info1(libubi, dev_info.dev_num, req.vol_id, &vol_info); 266 if (err) { 267 fprintf(stderr, "cannot get information about newly created UBI volume"); 268 return -1; 269 } 270 271 printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs); 272 ubiutils_print_bytes(vol_info.rsvd_bytes, 0); 273 printf("), LEB size "); 274 ubiutils_print_bytes(vol_info.leb_size, 1); 275 printf(", %s, name \"%s\", alignment %d\n", 276 req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static", 277 vol_info.name, vol_info.alignment); 278 279 return 0; 280 } 281 282 int ubiupdatevol(libubi_t libubi, char *node, char *file) 283 { 284 struct ubi_vol_info vol_info; 285 int err = ubi_get_vol_info(libubi, node, &vol_info); 286 287 if (err) { 288 fprintf(stderr, "cannot get information about UBI volume \"%s\"", 289 node); 290 return -1; 291 } 292 293 return update_volume(libubi, &vol_info, node, file, 0); 294 } 295 296 int ubitruncatevol(libubi_t libubi, char *node) 297 { 298 int err, fd; 299 300 fd = open(node, O_RDWR); 301 if (fd == -1) { 302 fprintf(stderr, "cannot open \"%s\"", node); 303 return -1; 304 } 305 306 err = ubi_update_start(libubi, fd, 0); 307 if (err) { 308 fprintf(stderr, "cannot truncate volume \"%s\"", node); 309 close(fd); 310 return -1; 311 } 312 313 close(fd); 314 return 0; 315 } 316
This page was automatically generated by LXR 0.3.1. • OpenWrt