"Das U-Boot" Source Tree
at master 917 lines 20 kB view raw
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 <command.h> 15#include <env.h> 16#include <exports.h> 17#include <led.h> 18#include <malloc.h> 19#include <memalign.h> 20#include <mtd.h> 21#include <nand.h> 22#include <onenand_uboot.h> 23#include <dm/devres.h> 24#include <linux/mtd/mtd.h> 25#include <linux/mtd/partitions.h> 26#include <linux/err.h> 27#include <ubi_uboot.h> 28#include <linux/errno.h> 29#include <jffs2/load_kernel.h> 30#include <linux/log2.h> 31 32#undef ubi_msg 33#define ubi_msg(fmt, ...) printf("UBI: " fmt "\n", ##__VA_ARGS__) 34 35/* Private own data */ 36static struct ubi_device *ubi; 37 38#ifdef CONFIG_CMD_UBIFS 39#include <ubifs_uboot.h> 40#endif 41 42static void display_volume_info(struct ubi_device *ubi) 43{ 44 int i; 45 46 for (i = 0; i < (ubi->vtbl_slots + 1); i++) { 47 if (!ubi->volumes[i]) 48 continue; /* Empty record */ 49 ubi_dump_vol_info(ubi->volumes[i]); 50 } 51} 52 53static void display_ubi_info(struct ubi_device *ubi) 54{ 55 ubi_msg("MTD device name: \"%s\"", ubi->mtd->name); 56 ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); 57 ubi_msg("physical eraseblock size: %d bytes (%d KiB)", 58 ubi->peb_size, ubi->peb_size >> 10); 59 ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); 60 ubi_msg("number of good PEBs: %d", ubi->good_peb_count); 61 ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); 62 ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); 63 ubi_msg("VID header offset: %d (aligned %d)", 64 ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); 65 ubi_msg("data offset: %d", ubi->leb_start); 66 ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); 67 ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); 68 ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); 69 ubi_msg("number of user volumes: %d", 70 ubi->vol_count - UBI_INT_VOL_COUNT); 71 ubi_msg("available PEBs: %d", ubi->avail_pebs); 72 ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs); 73 ubi_msg("number of PEBs reserved for bad PEB handling: %d", 74 ubi->beb_rsvd_pebs); 75 ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); 76} 77 78static int ubi_info(int layout) 79{ 80 if (layout) 81 display_volume_info(ubi); 82 else 83 display_ubi_info(ubi); 84 85 return 0; 86} 87 88static int ubi_list(const char *var, int numeric) 89{ 90 size_t namelen, len, size; 91 char *str, *str2; 92 int i; 93 94 if (!var) { 95 for (i = 0; i < (ubi->vtbl_slots + 1); i++) { 96 if (!ubi->volumes[i]) 97 continue; 98 if (ubi->volumes[i]->vol_id >= UBI_INTERNAL_VOL_START) 99 continue; 100 printf("%d: %s\n", 101 ubi->volumes[i]->vol_id, 102 ubi->volumes[i]->name); 103 } 104 return 0; 105 } 106 107 len = 0; 108 size = 16; 109 str = malloc(size); 110 if (!str) 111 return 1; 112 113 for (i = 0; i < (ubi->vtbl_slots + 1); i++) { 114 if (!ubi->volumes[i]) 115 continue; 116 if (ubi->volumes[i]->vol_id >= UBI_INTERNAL_VOL_START) 117 continue; 118 119 if (numeric) 120 namelen = 10; /* strlen(stringify(INT_MAX)) */ 121 else 122 namelen = strlen(ubi->volumes[i]->name); 123 124 if (len + namelen + 1 > size) { 125 size = roundup_pow_of_two(len + namelen + 1) * 2; 126 str2 = realloc(str, size); 127 if (!str2) { 128 free(str); 129 return 1; 130 } 131 str = str2; 132 } 133 134 if (len) 135 str[len++] = ' '; 136 137 if (numeric) { 138 len += sprintf(str + len, "%d", ubi->volumes[i]->vol_id) + 1; 139 } else { 140 memcpy(str + len, ubi->volumes[i]->name, namelen); 141 len += namelen; 142 str[len] = 0; 143 } 144 } 145 146 env_set(var, str); 147 free(str); 148 149 return 0; 150} 151 152static int ubi_check_volumename(const struct ubi_volume *vol, char *name) 153{ 154 return strcmp(vol->name, name); 155} 156 157static int ubi_check(char *name) 158{ 159 int i; 160 161 for (i = 0; i < (ubi->vtbl_slots + 1); i++) { 162 if (!ubi->volumes[i]) 163 continue; /* Empty record */ 164 165 if (!ubi_check_volumename(ubi->volumes[i], name)) 166 return 0; 167 } 168 169 return 1; 170} 171 172static int verify_mkvol_req(const struct ubi_device *ubi, 173 const struct ubi_mkvol_req *req) 174{ 175 int n, err = EINVAL; 176 177 if (req->bytes < 0 || req->alignment < 0 || req->vol_type < 0 || 178 req->name_len < 0) 179 goto bad; 180 181 if ((req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots) && 182 req->vol_id != UBI_VOL_NUM_AUTO) 183 goto bad; 184 185 if (req->alignment == 0) 186 goto bad; 187 188 if (req->bytes == 0) { 189 printf("No space left in UBI device!\n"); 190 err = ENOMEM; 191 goto bad; 192 } 193 194 if (req->vol_type != UBI_DYNAMIC_VOLUME && 195 req->vol_type != UBI_STATIC_VOLUME) 196 goto bad; 197 198 if (req->alignment > ubi->leb_size) 199 goto bad; 200 201 n = req->alignment % ubi->min_io_size; 202 if (req->alignment != 1 && n) 203 goto bad; 204 205 if (req->name_len > UBI_VOL_NAME_MAX) { 206 printf("Name too long!\n"); 207 err = ENAMETOOLONG; 208 goto bad; 209 } 210 211 return 0; 212bad: 213 return err; 214} 215 216static int ubi_create_vol(char *volume, int64_t size, int dynamic, int vol_id, 217 bool skipcheck) 218{ 219 struct ubi_mkvol_req req; 220 int err; 221 222 if (dynamic) 223 req.vol_type = UBI_DYNAMIC_VOLUME; 224 else 225 req.vol_type = UBI_STATIC_VOLUME; 226 227 req.vol_id = vol_id; 228 req.alignment = 1; 229 req.bytes = size; 230 231 strcpy(req.name, volume); 232 req.name_len = strlen(volume); 233 req.name[req.name_len] = '\0'; 234 req.flags = 0; 235 if (skipcheck) 236 req.flags |= UBI_VOL_SKIP_CRC_CHECK_FLG; 237 238 /* It's duplicated at drivers/mtd/ubi/cdev.c */ 239 err = verify_mkvol_req(ubi, &req); 240 if (err) { 241 printf("verify_mkvol_req failed %d\n", err); 242 return err; 243 } 244 printf("Creating %s volume %s of size %lld\n", 245 dynamic ? "dynamic" : "static", volume, size); 246 /* Call real ubi create volume */ 247 return ubi_create_volume(ubi, &req); 248} 249 250static struct ubi_volume *ubi_find_volume(char *volume) 251{ 252 struct ubi_volume *vol; 253 int i; 254 255 for (i = 0; i < ubi->vtbl_slots; i++) { 256 vol = ubi->volumes[i]; 257 if (vol && !strcmp(vol->name, volume)) 258 return vol; 259 } 260 261 printf("Volume %s not found!\n", volume); 262 return NULL; 263} 264 265static int ubi_remove_vol(char *volume) 266{ 267 int err, reserved_pebs, i; 268 struct ubi_volume *vol; 269 270 vol = ubi_find_volume(volume); 271 if (vol == NULL) 272 return ENODEV; 273 274 printf("Remove UBI volume %s (id %d)\n", vol->name, vol->vol_id); 275 276 if (ubi->ro_mode) { 277 printf("It's read-only mode\n"); 278 err = EROFS; 279 goto out_err; 280 } 281 282 err = ubi_change_vtbl_record(ubi, vol->vol_id, NULL); 283 if (err) { 284 printf("Error changing Vol tabel record err=%x\n", err); 285 goto out_err; 286 } 287 reserved_pebs = vol->reserved_pebs; 288 for (i = 0; i < vol->reserved_pebs; i++) { 289 err = ubi_eba_unmap_leb(ubi, vol, i); 290 if (err) 291 goto out_err; 292 } 293 294 kfree(vol->eba_tbl); 295 ubi->volumes[vol->vol_id]->eba_tbl = NULL; 296 ubi->volumes[vol->vol_id] = NULL; 297 298 ubi->rsvd_pebs -= reserved_pebs; 299 ubi->avail_pebs += reserved_pebs; 300 i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs; 301 if (i > 0) { 302 i = ubi->avail_pebs >= i ? i : ubi->avail_pebs; 303 ubi->avail_pebs -= i; 304 ubi->rsvd_pebs += i; 305 ubi->beb_rsvd_pebs += i; 306 if (i > 0) 307 ubi_msg("reserve more %d PEBs", i); 308 } 309 ubi->vol_count -= 1; 310 311 return 0; 312out_err: 313 ubi_err(ubi, "cannot remove volume %s, error %d", volume, err); 314 if (err < 0) 315 err = -err; 316 return err; 317} 318 319static int ubi_rename_vol(char *oldname, char *newname) 320{ 321 struct ubi_volume *vol; 322 struct ubi_rename_entry rename; 323 struct ubi_volume_desc desc; 324 struct list_head list; 325 326 vol = ubi_find_volume(oldname); 327 if (!vol) { 328 printf("%s: volume %s doesn't exist\n", __func__, oldname); 329 return ENODEV; 330 } 331 332 if (!ubi_check(newname)) { 333 printf("%s: volume %s already exist\n", __func__, newname); 334 return EINVAL; 335 } 336 337 printf("Rename UBI volume %s to %s\n", oldname, newname); 338 339 if (ubi->ro_mode) { 340 printf("%s: ubi device is in read-only mode\n", __func__); 341 return EROFS; 342 } 343 344 rename.new_name_len = strlen(newname); 345 strcpy(rename.new_name, newname); 346 rename.remove = 0; 347 desc.vol = vol; 348 desc.mode = 0; 349 rename.desc = &desc; 350 INIT_LIST_HEAD(&rename.list); 351 INIT_LIST_HEAD(&list); 352 list_add(&rename.list, &list); 353 354 return ubi_rename_volumes(ubi, &list); 355} 356 357static int ubi_volume_continue_write(char *volume, void *buf, size_t size) 358{ 359 int err; 360 struct ubi_volume *vol; 361 362 vol = ubi_find_volume(volume); 363 if (vol == NULL) 364 return ENODEV; 365 366 if (!vol->updating) { 367 printf("UBI volume update was not initiated\n"); 368 return EINVAL; 369 } 370 371 err = ubi_more_update_data(ubi, vol, buf, size); 372 if (err < 0) { 373 printf("Couldnt or partially wrote data\n"); 374 return -err; 375 } 376 377 if (err) { 378 size = err; 379 380 err = ubi_check_volume(ubi, vol->vol_id); 381 if (err < 0) 382 return -err; 383 384 if (err) { 385 ubi_warn(ubi, "volume %d on UBI device %d is corrupt", 386 vol->vol_id, ubi->ubi_num); 387 vol->corrupted = 1; 388 } 389 390 vol->checked = 1; 391 ubi_gluebi_updated(vol); 392 } 393 394 return 0; 395} 396 397int ubi_volume_begin_write(char *volume, void *buf, size_t size, 398 size_t full_size) 399{ 400 int err; 401 int rsvd_bytes; 402 struct ubi_volume *vol; 403 404 vol = ubi_find_volume(volume); 405 if (vol == NULL) 406 return ENODEV; 407 408 rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); 409 if (size > rsvd_bytes) { 410 printf("size > volume size! Aborting!\n"); 411 return EINVAL; 412 } 413 414 err = ubi_start_update(ubi, vol, full_size); 415 if (err < 0) { 416 printf("Cannot start volume update\n"); 417 return -err; 418 } 419 420 /* The volume is just wiped out */ 421 if (!full_size) 422 return 0; 423 424 return ubi_volume_continue_write(volume, buf, size); 425} 426 427static int ubi_volume_offset_write(char *volume, void *buf, loff_t offset, 428 size_t size) 429{ 430 int len, tbuf_size, ret; 431 u64 lnum; 432 struct ubi_volume *vol; 433 loff_t off = offset; 434 void *tbuf; 435 436 vol = ubi_find_volume(volume); 437 if (!vol) 438 return -ENODEV; 439 440 if (size > vol->reserved_pebs * (ubi->leb_size - vol->data_pad)) 441 return -EINVAL; 442 443 tbuf_size = vol->usable_leb_size; 444 tbuf = malloc_cache_aligned(tbuf_size); 445 if (!tbuf) 446 return -ENOMEM; 447 448 lnum = off; 449 off = do_div(lnum, vol->usable_leb_size); 450 451 do { 452 struct ubi_volume_desc desc = { 453 .vol = vol, 454 .mode = UBI_READWRITE, 455 }; 456 457 len = size > tbuf_size ? tbuf_size : size; 458 if (off + len >= vol->usable_leb_size) 459 len = vol->usable_leb_size - off; 460 461 ret = ubi_read(&desc, (int)lnum, tbuf, 0, tbuf_size); 462 if (ret) { 463 pr_err("Failed to read leb %lld (%d)\n", lnum, ret); 464 goto exit; 465 } 466 467 memcpy(tbuf + off, buf, len); 468 469 ret = ubi_leb_change(&desc, (int)lnum, tbuf, tbuf_size); 470 if (ret) { 471 pr_err("Failed to write leb %lld (%d)\n", lnum, ret); 472 goto exit; 473 } 474 475 off += len; 476 if (off >= vol->usable_leb_size) { 477 lnum++; 478 off -= vol->usable_leb_size; 479 } 480 481 buf += len; 482 size -= len; 483 } while (size); 484 485exit: 486 free(tbuf); 487 return ret; 488} 489 490int ubi_volume_write(char *volume, void *buf, loff_t offset, size_t size) 491{ 492 int ret; 493 494 led_activity_blink(); 495 496 if (!offset) 497 ret = ubi_volume_begin_write(volume, buf, size, size); 498 else 499 ret = ubi_volume_offset_write(volume, buf, offset, size); 500 501 led_activity_off(); 502 503 return ret; 504} 505 506int ubi_volume_read(char *volume, char *buf, loff_t offset, size_t size) 507{ 508 int err, lnum, off, len, tbuf_size; 509 void *tbuf; 510 unsigned long long tmp; 511 struct ubi_volume *vol; 512 loff_t offp = offset; 513 size_t len_read; 514 515 vol = ubi_find_volume(volume); 516 if (vol == NULL) 517 return ENODEV; 518 519 if (vol->updating) { 520 printf("updating"); 521 return EBUSY; 522 } 523 if (vol->upd_marker) { 524 printf("damaged volume, update marker is set"); 525 return EBADF; 526 } 527 if (offp == vol->used_bytes) 528 return 0; 529 530 if (size == 0) { 531 printf("No size specified -> Using max size (%lld)\n", vol->used_bytes); 532 size = vol->used_bytes; 533 } 534 535 printf("Read %zu bytes from volume %s to %p\n", size, volume, buf); 536 537 if (vol->corrupted) 538 printf("read from corrupted volume %d", vol->vol_id); 539 if (offp + size > vol->used_bytes) 540 size = vol->used_bytes - offp; 541 542 tbuf_size = vol->usable_leb_size; 543 if (size < tbuf_size) 544 tbuf_size = ALIGN(size, ubi->min_io_size); 545 tbuf = malloc_cache_aligned(tbuf_size); 546 if (!tbuf) { 547 printf("NO MEM\n"); 548 return ENOMEM; 549 } 550 len = size > tbuf_size ? tbuf_size : size; 551 552 tmp = offp; 553 off = do_div(tmp, vol->usable_leb_size); 554 lnum = tmp; 555 len_read = size; 556 do { 557 if (off + len >= vol->usable_leb_size) 558 len = vol->usable_leb_size - off; 559 560 err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0); 561 if (err) { 562 printf("read err %x\n", err); 563 err = -err; 564 break; 565 } 566 off += len; 567 if (off == vol->usable_leb_size) { 568 lnum += 1; 569 off -= vol->usable_leb_size; 570 } 571 572 size -= len; 573 offp += len; 574 575 memcpy(buf, tbuf, len); 576 577 buf += len; 578 len = size > tbuf_size ? tbuf_size : size; 579 } while (size); 580 581 if (!size) 582 env_set_hex("filesize", len_read); 583 584 free(tbuf); 585 return err; 586} 587 588static int ubi_dev_scan(struct mtd_info *info, const char *vid_header_offset) 589{ 590 char ubi_mtd_param_buffer[80]; 591 int err; 592 593 if (!vid_header_offset) 594 sprintf(ubi_mtd_param_buffer, "%s", info->name); 595 else 596 sprintf(ubi_mtd_param_buffer, "%s,%s", info->name, 597 vid_header_offset); 598 599 err = ubi_mtd_param_parse(ubi_mtd_param_buffer, NULL); 600 if (err) 601 return -err; 602 603 err = ubi_init(); 604 if (err) 605 return -err; 606 607 return 0; 608} 609 610static int ubi_set_skip_check(char *volume, bool skip_check) 611{ 612 struct ubi_vtbl_record vtbl_rec; 613 struct ubi_volume *vol; 614 615 vol = ubi_find_volume(volume); 616 if (!vol) 617 return ENODEV; 618 619 printf("%sing skip_check on volume %s\n", 620 skip_check ? "Sett" : "Clear", volume); 621 622 vtbl_rec = ubi->vtbl[vol->vol_id]; 623 if (skip_check) { 624 vtbl_rec.flags |= UBI_VTBL_SKIP_CRC_CHECK_FLG; 625 vol->skip_check = 1; 626 } else { 627 vtbl_rec.flags &= ~UBI_VTBL_SKIP_CRC_CHECK_FLG; 628 vol->skip_check = 0; 629 } 630 631 return ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec); 632} 633 634static int ubi_detach(void) 635{ 636#ifdef CONFIG_CMD_UBIFS 637 /* 638 * Automatically unmount UBIFS partition when user 639 * changes the UBI device. Otherwise the following 640 * UBIFS commands will crash. 641 */ 642 if (ubifs_is_mounted()) 643 cmd_ubifs_umount(); 644#endif 645 646 /* 647 * Call ubi_exit() before re-initializing the UBI subsystem 648 */ 649 if (ubi) 650 ubi_exit(); 651 652 ubi = NULL; 653 654 return 0; 655} 656 657int ubi_part(char *part_name, const char *vid_header_offset) 658{ 659 struct mtd_info *mtd; 660 int err; 661 662 if (ubi && ubi->mtd && !strcmp(ubi->mtd->name, part_name)) { 663 printf("UBI partition '%s' already selected\n", part_name); 664 return 0; 665 } 666 667 ubi_detach(); 668 669 mtd_probe_devices(); 670 mtd = get_mtd_device_nm(part_name); 671 if (IS_ERR(mtd)) { 672 printf("Partition %s not found!\n", part_name); 673 return 1; 674 } 675 put_mtd_device(mtd); 676 677 err = ubi_dev_scan(mtd, vid_header_offset); 678 if (err) { 679 printf("UBI init error %d\n", err); 680 printf("Please check, if the correct MTD partition is used (size big enough?)\n"); 681 return err; 682 } 683 684 ubi = ubi_devices[0]; 685 686 return 0; 687} 688 689static int do_ubi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 690{ 691 int64_t size; 692 ulong addr = 0; 693 bool skipcheck = false; 694 695 if (argc < 2) 696 return CMD_RET_USAGE; 697 698 if (strcmp(argv[1], "detach") == 0) 699 return ubi_detach(); 700 701 if (strcmp(argv[1], "part") == 0) { 702 const char *vid_header_offset = NULL; 703 704 /* Print current partition */ 705 if (argc == 2) { 706 if (!ubi) { 707 printf("Error, no UBI device selected!\n"); 708 return 1; 709 } 710 711 printf("Device %d: %s, MTD partition %s\n", 712 ubi->ubi_num, ubi->ubi_name, ubi->mtd->name); 713 return 0; 714 } 715 716 if (argc < 3) 717 return CMD_RET_USAGE; 718 719 if (argc > 3) 720 vid_header_offset = argv[3]; 721 722 return ubi_part(argv[2], vid_header_offset); 723 } 724 725 if ((strcmp(argv[1], "part") != 0) && !ubi) { 726 printf("Error, no UBI device selected!\n"); 727 return 1; 728 } 729 730 if (strcmp(argv[1], "info") == 0) { 731 int layout = 0; 732 if (argc > 2 && !strncmp(argv[2], "l", 1)) 733 layout = 1; 734 return ubi_info(layout); 735 } 736 737 if (strcmp(argv[1], "list") == 0) { 738 int numeric = 0; 739 if (argc >= 3 && argv[2][0] == '-') { 740 if (strcmp(argv[2], "-numeric") == 0) 741 numeric = 1; 742 else 743 return CMD_RET_USAGE; 744 } 745 if (!numeric && argc != 2 && argc != 3) 746 return CMD_RET_USAGE; 747 if (numeric && argc != 3 && argc != 4) 748 return CMD_RET_USAGE; 749 return ubi_list(argv[numeric ? 3 : 2], numeric); 750 } 751 752 if (strcmp(argv[1], "check") == 0) { 753 if (argc > 2) 754 return ubi_check(argv[2]); 755 756 printf("Error, no volume name passed\n"); 757 return 1; 758 } 759 760 if (strncmp(argv[1], "create", 6) == 0) { 761 int dynamic = 1; /* default: dynamic volume */ 762 int id = UBI_VOL_NUM_AUTO; 763 764 /* Use maximum available size */ 765 size = 0; 766 767 /* E.g., create volume with "skipcheck" bit set */ 768 if (argc == 7) { 769 skipcheck = strncmp(argv[6], "--skipcheck", 11) == 0; 770 argc--; 771 } 772 773 /* E.g., create volume size type vol_id */ 774 if (argc == 6) { 775 id = simple_strtoull(argv[5], NULL, 16); 776 argc--; 777 } 778 779 /* E.g., create volume size type */ 780 if (argc == 5) { 781 if (strncmp(argv[4], "s", 1) == 0) 782 dynamic = 0; 783 else if (strncmp(argv[4], "d", 1) != 0) { 784 printf("Incorrect type\n"); 785 return 1; 786 } 787 argc--; 788 } 789 /* E.g., create volume size */ 790 if (argc == 4) { 791 if (argv[3][0] != '-') 792 size = simple_strtoull(argv[3], NULL, 16); 793 argc--; 794 } 795 /* Use maximum available size */ 796 if (!size) { 797 size = (int64_t)ubi->avail_pebs * ubi->leb_size; 798 printf("No size specified -> Using max size (%lld)\n", size); 799 } 800 /* E.g., create volume */ 801 if (argc == 3) { 802 return ubi_create_vol(argv[2], size, dynamic, id, 803 skipcheck); 804 } 805 } 806 807 if (strncmp(argv[1], "remove", 6) == 0) { 808 /* E.g., remove volume */ 809 if (argc == 3) 810 return ubi_remove_vol(argv[2]); 811 } 812 813 if (IS_ENABLED(CONFIG_CMD_UBI_RENAME) && !strncmp(argv[1], "rename", 6)) 814 return ubi_rename_vol(argv[2], argv[3]); 815 816 if (strncmp(argv[1], "skipcheck", 9) == 0) { 817 /* E.g., change skip_check flag */ 818 if (argc == 4) { 819 skipcheck = strncmp(argv[3], "on", 2) == 0; 820 return ubi_set_skip_check(argv[2], skipcheck); 821 } 822 } 823 824 if (strncmp(argv[1], "write", 5) == 0) { 825 int ret; 826 827 if (argc < 5) { 828 printf("Please see usage\n"); 829 return 1; 830 } 831 832 addr = hextoul(argv[2], NULL); 833 size = hextoul(argv[4], NULL); 834 835 if (strlen(argv[1]) == 10 && 836 strncmp(argv[1] + 5, ".part", 5) == 0) { 837 if (argc < 6) { 838 ret = ubi_volume_continue_write(argv[3], 839 (void *)addr, size); 840 } else { 841 size_t full_size; 842 full_size = hextoul(argv[5], NULL); 843 ret = ubi_volume_begin_write(argv[3], 844 (void *)addr, size, full_size); 845 } 846 } else { 847 ret = ubi_volume_write(argv[3], (void *)addr, 0, size); 848 } 849 if (!ret) { 850 printf("%lld bytes written to volume %s\n", size, 851 argv[3]); 852 } 853 854 return ret; 855 } 856 857 if (strncmp(argv[1], "read", 4) == 0) { 858 size = 0; 859 860 /* E.g., read volume size */ 861 if (argc == 5) { 862 size = hextoul(argv[4], NULL); 863 argc--; 864 } 865 866 /* E.g., read volume */ 867 if (argc == 4) { 868 addr = hextoul(argv[2], NULL); 869 argc--; 870 } 871 872 if (argc == 3) { 873 return ubi_volume_read(argv[3], (char *)addr, 0, size); 874 } 875 } 876 877 printf("Please see usage\n"); 878 return 1; 879} 880 881U_BOOT_CMD( 882 ubi, 7, 1, do_ubi, 883 "ubi commands", 884 "detach" 885 " - detach ubi from a mtd partition\n" 886 "ubi part [part] [offset]\n" 887 " - Show or set current partition (with optional VID" 888 " header offset)\n" 889 "ubi info [l[ayout]]" 890 " - Display volume and ubi layout information\n" 891 "ubi list [flags]" 892 " - print the list of volumes\n" 893 "ubi list [flags] <varname>" 894 " - set environment variable to the list of volumes" 895 " (flags can be -numeric)\n" 896 "ubi check volumename" 897 " - check if volumename exists\n" 898 "ubi create[vol] volume [size] [type] [id] [--skipcheck]\n" 899 " - create volume name with size ('-' for maximum" 900 " available size)\n" 901 "ubi write[vol] address volume size" 902 " - Write volume from address with size\n" 903 "ubi write.part address volume size [fullsize]\n" 904 " - Write part of a volume from address\n" 905 "ubi read[vol] address volume [size]" 906 " - Read volume to address with size\n" 907 "ubi remove[vol] volume" 908 " - Remove volume\n" 909#if IS_ENABLED(CONFIG_CMD_UBI_RENAME) 910 "ubi rename oldname newname\n" 911#endif 912 "ubi skipcheck volume on/off - Set or clear skip_check flag in volume header\n" 913 "[Legends]\n" 914 " volume: character name\n" 915 " size: specified in bytes\n" 916 " type: s[tatic] or d[ynamic] (default=dynamic)" 917);