1 /* 2 * Unsorted Block Image commands 3 * 4 * Copyright (C) 2008 Samsung Electronics 5 * Kyungmin Park <kyungmin.park@samsung.com> 6 * 7 * Copyright 2008-2009 Stefan Roese <sr@denx.de>, DENX Software Engineering 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <common.h> 15 #include <command.h> 16 #include <exports.h> 17 #include <memalign.h> 18 #include <mtd.h> 19 #include <nand.h> 20 #include <onenand_uboot.h> 21 #include <linux/mtd/mtd.h> 22 #include <linux/mtd/partitions.h> 23 #include <linux/err.h> 24 #include <ubi_uboot.h> 25 #include <linux/errno.h> 26 #include <jffs2/load_kernel.h> 27 28 #undef ubi_msg 29 #define ubi_msg(fmt, ...) printf("UBI: " fmt "\n", ##__VA_ARGS__) 30 31 /* Private own data */ 32 static struct ubi_device *ubi; 33 34 #ifdef CONFIG_CMD_UBIFS 35 #include <ubifs_uboot.h> 36 #endif 37 38 static void display_volume_info(struct ubi_device *ubi) 39 { 40 int i; 41 42 for (i = 0; i < (ubi->vtbl_slots + 1); i++) { 43 if (!ubi->volumes[i]) 44 continue; /* Empty record */ 45 ubi_dump_vol_info(ubi->volumes[i]); 46 } 47 } 48 49 static void display_ubi_info(struct ubi_device *ubi) 50 { 51 ubi_msg("MTD device name: \"%s\"", ubi->mtd->name); 52 ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); 53 ubi_msg("physical eraseblock size: %d bytes (%d KiB)", 54 ubi->peb_size, ubi->peb_size >> 10); 55 ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); 56 ubi_msg("number of good PEBs: %d", ubi->good_peb_count); 57 ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); 58 ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); 59 ubi_msg("VID header offset: %d (aligned %d)", 60 ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); 61 ubi_msg("data offset: %d", ubi->leb_start); 62 ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); 63 ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); 64 ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); 65 ubi_msg("number of user volumes: %d", 66 ubi->vol_count - UBI_INT_VOL_COUNT); 67 ubi_msg("available PEBs: %d", ubi->avail_pebs); 68 ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs); 69 ubi_msg("number of PEBs reserved for bad PEB handling: %d", 70 ubi->beb_rsvd_pebs); 71 ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); 72 } 73 74 static int ubi_info(int layout) 75 { 76 if (layout) 77 display_volume_info(ubi); 78 else 79 display_ubi_info(ubi); 80 81 return 0; 82 } 83 84 static int ubi_check_volumename(const struct ubi_volume *vol, char *name) 85 { 86 return strcmp(vol->name, name); 87 } 88 89 static int ubi_check(char *name) 90 { 91 int i; 92 93 for (i = 0; i < (ubi->vtbl_slots + 1); i++) { 94 if (!ubi->volumes[i]) 95 continue; /* Empty record */ 96 97 if (!ubi_check_volumename(ubi->volumes[i], name)) 98 return 0; 99 } 100 101 return 1; 102 } 103 104 static int verify_mkvol_req(const struct ubi_device *ubi, 105 const struct ubi_mkvol_req *req) 106 { 107 int n, err = EINVAL; 108 109 if (req->bytes < 0 || req->alignment < 0 || req->vol_type < 0 || 110 req->name_len < 0) 111 goto bad; 112 113 if ((req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots) && 114 req->vol_id != UBI_VOL_NUM_AUTO) 115 goto bad; 116 117 if (req->alignment == 0) 118 goto bad; 119 120 if (req->bytes == 0) { 121 printf("No space left in UBI device!\n"); 122 err = ENOMEM; 123 goto bad; 124 } 125 126 if (req->vol_type != UBI_DYNAMIC_VOLUME && 127 req->vol_type != UBI_STATIC_VOLUME) 128 goto bad; 129 130 if (req->alignment > ubi->leb_size) 131 goto bad; 132 133 n = req->alignment % ubi->min_io_size; 134 if (req->alignment != 1 && n) 135 goto bad; 136 137 if (req->name_len > UBI_VOL_NAME_MAX) { 138 printf("Name too long!\n"); 139 err = ENAMETOOLONG; 140 goto bad; 141 } 142 143 return 0; 144 bad: 145 return err; 146 } 147 148 static int ubi_create_vol(char *volume, int64_t size, int dynamic, int vol_id) 149 { 150 struct ubi_mkvol_req req; 151 int err; 152 153 if (dynamic) 154 req.vol_type = UBI_DYNAMIC_VOLUME; 155 else 156 req.vol_type = UBI_STATIC_VOLUME; 157 158 req.vol_id = vol_id; 159 req.alignment = 1; 160 req.bytes = size; 161 162 strcpy(req.name, volume); 163 req.name_len = strlen(volume); 164 req.name[req.name_len] = '\0'; 165 req.padding1 = 0; 166 /* It's duplicated at drivers/mtd/ubi/cdev.c */ 167 err = verify_mkvol_req(ubi, &req); 168 if (err) { 169 printf("verify_mkvol_req failed %d\n", err); 170 return err; 171 } 172 printf("Creating %s volume %s of size %lld\n", 173 dynamic ? "dynamic" : "static", volume, size); 174 /* Call real ubi create volume */ 175 return ubi_create_volume(ubi, &req); 176 } 177 178 static struct ubi_volume *ubi_find_volume(char *volume) 179 { 180 struct ubi_volume *vol = NULL; 181 int i; 182 183 for (i = 0; i < ubi->vtbl_slots; i++) { 184 vol = ubi->volumes[i]; 185 if (vol && !strcmp(vol->name, volume)) 186 return vol; 187 } 188 189 printf("Volume %s not found!\n", volume); 190 return NULL; 191 } 192 193 static int ubi_remove_vol(char *volume) 194 { 195 int err, reserved_pebs, i; 196 struct ubi_volume *vol; 197 198 vol = ubi_find_volume(volume); 199 if (vol == NULL) 200 return ENODEV; 201 202 printf("Remove UBI volume %s (id %d)\n", vol->name, vol->vol_id); 203 204 if (ubi->ro_mode) { 205 printf("It's read-only mode\n"); 206 err = EROFS; 207 goto out_err; 208 } 209 210 err = ubi_change_vtbl_record(ubi, vol->vol_id, NULL); 211 if (err) { 212 printf("Error changing Vol tabel record err=%x\n", err); 213 goto out_err; 214 } 215 reserved_pebs = vol->reserved_pebs; 216 for (i = 0; i < vol->reserved_pebs; i++) { 217 err = ubi_eba_unmap_leb(ubi, vol, i); 218 if (err) 219 goto out_err; 220 } 221 222 kfree(vol->eba_tbl); 223 ubi->volumes[vol->vol_id]->eba_tbl = NULL; 224 ubi->volumes[vol->vol_id] = NULL; 225 226 ubi->rsvd_pebs -= reserved_pebs; 227 ubi->avail_pebs += reserved_pebs; 228 i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs; 229 if (i > 0) { 230 i = ubi->avail_pebs >= i ? i : ubi->avail_pebs; 231 ubi->avail_pebs -= i; 232 ubi->rsvd_pebs += i; 233 ubi->beb_rsvd_pebs += i; 234 if (i > 0) 235 ubi_msg("reserve more %d PEBs", i); 236 } 237 ubi->vol_count -= 1; 238 239 return 0; 240 out_err: 241 ubi_err(ubi, "cannot remove volume %s, error %d", volume, err); 242 if (err < 0) 243 err = -err; 244 return err; 245 } 246 247 static int ubi_volume_continue_write(char *volume, void *buf, size_t size) 248 { 249 int err = 1; 250 struct ubi_volume *vol; 251 252 vol = ubi_find_volume(volume); 253 if (vol == NULL) 254 return ENODEV; 255 256 err = ubi_more_update_data(ubi, vol, buf, size); 257 if (err < 0) { 258 printf("Couldnt or partially wrote data\n"); 259 return -err; 260 } 261 262 if (err) { 263 size = err; 264 265 err = ubi_check_volume(ubi, vol->vol_id); 266 if (err < 0) 267 return -err; 268 269 if (err) { 270 ubi_warn(ubi, "volume %d on UBI device %d is corrupt", 271 vol->vol_id, ubi->ubi_num); 272 vol->corrupted = 1; 273 } 274 275 vol->checked = 1; 276 ubi_gluebi_updated(vol); 277 } 278 279 return 0; 280 } 281 282 int ubi_volume_begin_write(char *volume, void *buf, size_t size, 283 size_t full_size) 284 { 285 int err = 1; 286 int rsvd_bytes = 0; 287 struct ubi_volume *vol; 288 289 vol = ubi_find_volume(volume); 290 if (vol == NULL) 291 return ENODEV; 292 293 rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); 294 if (size > rsvd_bytes) { 295 printf("size > volume size! Aborting!\n"); 296 return EINVAL; 297 } 298 299 err = ubi_start_update(ubi, vol, full_size); 300 if (err < 0) { 301 printf("Cannot start volume update\n"); 302 return -err; 303 } 304 305 return ubi_volume_continue_write(volume, buf, size); 306 } 307 308 int ubi_volume_write(char *volume, void *buf, size_t size) 309 { 310 return ubi_volume_begin_write(volume, buf, size, size); 311 } 312 313 int ubi_volume_read(char *volume, char *buf, size_t size) 314 { 315 int err, lnum, off, len, tbuf_size; 316 void *tbuf; 317 unsigned long long tmp; 318 struct ubi_volume *vol; 319 loff_t offp = 0; 320 size_t len_read; 321 322 vol = ubi_find_volume(volume); 323 if (vol == NULL) 324 return ENODEV; 325 326 if (vol->updating) { 327 printf("updating"); 328 return EBUSY; 329 } 330 if (vol->upd_marker) { 331 printf("damaged volume, update marker is set"); 332 return EBADF; 333 } 334 if (offp == vol->used_bytes) 335 return 0; 336 337 if (size == 0) { 338 printf("No size specified -> Using max size (%lld)\n", vol->used_bytes); 339 size = vol->used_bytes; 340 } 341 342 printf("Read %zu bytes from volume %s to %p\n", size, volume, buf); 343 344 if (vol->corrupted) 345 printf("read from corrupted volume %d", vol->vol_id); 346 if (offp + size > vol->used_bytes) 347 size = vol->used_bytes - offp; 348 349 tbuf_size = vol->usable_leb_size; 350 if (size < tbuf_size) 351 tbuf_size = ALIGN(size, ubi->min_io_size); 352 tbuf = malloc_cache_aligned(tbuf_size); 353 if (!tbuf) { 354 printf("NO MEM\n"); 355 return ENOMEM; 356 } 357 len = size > tbuf_size ? tbuf_size : size; 358 359 tmp = offp; 360 off = do_div(tmp, vol->usable_leb_size); 361 lnum = tmp; 362 len_read = size; 363 do { 364 if (off + len >= vol->usable_leb_size) 365 len = vol->usable_leb_size - off; 366 367 err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0); 368 if (err) { 369 printf("read err %x\n", err); 370 err = -err; 371 break; 372 } 373 off += len; 374 if (off == vol->usable_leb_size) { 375 lnum += 1; 376 off -= vol->usable_leb_size; 377 } 378 379 size -= len; 380 offp += len; 381 382 memcpy(buf, tbuf, len); 383 384 buf += len; 385 len = size > tbuf_size ? tbuf_size : size; 386 } while (size); 387 388 if (!size) 389 env_set_hex("filesize", len_read); 390 391 free(tbuf); 392 return err; 393 } 394 395 static int ubi_dev_scan(struct mtd_info *info, const char *vid_header_offset) 396 { 397 char ubi_mtd_param_buffer[80]; 398 int err; 399 400 if (!vid_header_offset) 401 sprintf(ubi_mtd_param_buffer, "%s", info->name); 402 else 403 sprintf(ubi_mtd_param_buffer, "%s,%s", info->name, 404 vid_header_offset); 405 406 err = ubi_mtd_param_parse(ubi_mtd_param_buffer, NULL); 407 if (err) 408 return -err; 409 410 err = ubi_init(); 411 if (err) 412 return -err; 413 414 return 0; 415 } 416 417 static int ubi_detach(void) 418 { 419 #ifdef CONFIG_CMD_UBIFS 420 /* 421 * Automatically unmount UBIFS partition when user 422 * changes the UBI device. Otherwise the following 423 * UBIFS commands will crash. 424 */ 425 if (ubifs_is_mounted()) 426 cmd_ubifs_umount(); 427 #endif 428 429 /* 430 * Call ubi_exit() before re-initializing the UBI subsystem 431 */ 432 if (ubi) 433 ubi_exit(); 434 435 ubi = NULL; 436 437 return 0; 438 } 439 440 int ubi_part(char *part_name, const char *vid_header_offset) 441 { 442 struct mtd_info *mtd; 443 int err = 0; 444 445 ubi_detach(); 446 447 mtd_probe_devices(); 448 mtd = get_mtd_device_nm(part_name); 449 if (IS_ERR(mtd)) { 450 printf("Partition %s not found!\n", part_name); 451 return 1; 452 } 453 put_mtd_device(mtd); 454 455 err = ubi_dev_scan(mtd, vid_header_offset); 456 if (err) { 457 printf("UBI init error %d\n", err); 458 printf("Please check, if the correct MTD partition is used (size big enough?)\n"); 459 return err; 460 } 461 462 ubi = ubi_devices[0]; 463 464 return 0; 465 } 466 467 static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 468 { 469 int64_t size = 0; 470 ulong addr = 0; 471 472 if (argc < 2) 473 return CMD_RET_USAGE; 474 475 if (strcmp(argv[1], "detach") == 0) 476 return ubi_detach(); 477 478 if (strcmp(argv[1], "part") == 0) { 479 const char *vid_header_offset = NULL; 480 481 /* Print current partition */ 482 if (argc == 2) { 483 if (!ubi) { 484 printf("Error, no UBI device selected!\n"); 485 return 1; 486 } 487 488 printf("Device %d: %s, MTD partition %s\n", 489 ubi->ubi_num, ubi->ubi_name, ubi->mtd->name); 490 return 0; 491 } 492 493 if (argc < 3) 494 return CMD_RET_USAGE; 495 496 if (argc > 3) 497 vid_header_offset = argv[3]; 498 499 return ubi_part(argv[2], vid_header_offset); 500 } 501 502 if ((strcmp(argv[1], "part") != 0) && !ubi) { 503 printf("Error, no UBI device selected!\n"); 504 return 1; 505 } 506 507 if (strcmp(argv[1], "info") == 0) { 508 int layout = 0; 509 if (argc > 2 && !strncmp(argv[2], "l", 1)) 510 layout = 1; 511 return ubi_info(layout); 512 } 513 514 if (strcmp(argv[1], "check") == 0) { 515 if (argc > 2) 516 return ubi_check(argv[2]); 517 518 printf("Error, no volume name passed\n"); 519 return 1; 520 } 521 522 if (strncmp(argv[1], "create", 6) == 0) { 523 int dynamic = 1; /* default: dynamic volume */ 524 int id = UBI_VOL_NUM_AUTO; 525 526 /* Use maximum available size */ 527 size = 0; 528 529 /* E.g., create volume size type vol_id */ 530 if (argc == 6) { 531 id = simple_strtoull(argv[5], NULL, 16); 532 argc--; 533 } 534 535 /* E.g., create volume size type */ 536 if (argc == 5) { 537 if (strncmp(argv[4], "s", 1) == 0) 538 dynamic = 0; 539 else if (strncmp(argv[4], "d", 1) != 0) { 540 printf("Incorrect type\n"); 541 return 1; 542 } 543 argc--; 544 } 545 /* E.g., create volume size */ 546 if (argc == 4) { 547 if (argv[3][0] != '-') 548 size = simple_strtoull(argv[3], NULL, 16); 549 argc--; 550 } 551 /* Use maximum available size */ 552 if (!size) { 553 size = (int64_t)ubi->avail_pebs * ubi->leb_size; 554 printf("No size specified -> Using max size (%lld)\n", size); 555 } 556 /* E.g., create volume */ 557 if (argc == 3) 558 return ubi_create_vol(argv[2], size, dynamic, id); 559 } 560 561 if (strncmp(argv[1], "remove", 6) == 0) { 562 /* E.g., remove volume */ 563 if (argc == 3) 564 return ubi_remove_vol(argv[2]); 565 } 566 567 if (strncmp(argv[1], "write", 5) == 0) { 568 int ret; 569 570 if (argc < 5) { 571 printf("Please see usage\n"); 572 return 1; 573 } 574 575 addr = simple_strtoul(argv[2], NULL, 16); 576 size = simple_strtoul(argv[4], NULL, 16); 577 578 if (strlen(argv[1]) == 10 && 579 strncmp(argv[1] + 5, ".part", 5) == 0) { 580 if (argc < 6) { 581 ret = ubi_volume_continue_write(argv[3], 582 (void *)addr, size); 583 } else { 584 size_t full_size; 585 full_size = simple_strtoul(argv[5], NULL, 16); 586 ret = ubi_volume_begin_write(argv[3], 587 (void *)addr, size, full_size); 588 } 589 } else { 590 ret = ubi_volume_write(argv[3], (void *)addr, size); 591 } 592 if (!ret) { 593 printf("%lld bytes written to volume %s\n", size, 594 argv[3]); 595 } 596 597 return ret; 598 } 599 600 if (strncmp(argv[1], "read", 4) == 0) { 601 size = 0; 602 603 /* E.g., read volume size */ 604 if (argc == 5) { 605 size = simple_strtoul(argv[4], NULL, 16); 606 argc--; 607 } 608 609 /* E.g., read volume */ 610 if (argc == 4) { 611 addr = simple_strtoul(argv[2], NULL, 16); 612 argc--; 613 } 614 615 if (argc == 3) { 616 return ubi_volume_read(argv[3], (char *)addr, size); 617 } 618 } 619 620 printf("Please see usage\n"); 621 return 1; 622 } 623 624 U_BOOT_CMD( 625 ubi, 6, 1, do_ubi, 626 "ubi commands", 627 "detach" 628 " - detach ubi from a mtd partition\n" 629 "ubi part [part] [offset]\n" 630 " - Show or set current partition (with optional VID" 631 " header offset)\n" 632 "ubi info [l[ayout]]" 633 " - Display volume and ubi layout information\n" 634 "ubi check volumename" 635 " - check if volumename exists\n" 636 "ubi create[vol] volume [size] [type] [id]\n" 637 " - create volume name with size ('-' for maximum" 638 " available size)\n" 639 "ubi write[vol] address volume size" 640 " - Write volume from address with size\n" 641 "ubi write.part address volume size [fullsize]\n" 642 " - Write part of a volume from address\n" 643 "ubi read[vol] address volume [size]" 644 " - Read volume to address with size\n" 645 "ubi remove[vol] volume" 646 " - Remove volume\n" 647 "[Legends]\n" 648 " volume: character name\n" 649 " size: specified in bytes\n" 650 " type: s[tatic] or d[ynamic] (default=dynamic)" 651 ); 652