/* * (c) Copyright 2012 by National Instruments, * Joe Hershberger <*****@*****.**> */ #include <common.h> #include <command.h> #include <environment.h> #include <errno.h> #include <malloc.h> #include <memalign.h> #include <search.h> #include <ubi_uboot.h> #undef crc32 DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_CMD_SAVEENV #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT static int env_ubi_save(void) { ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); int ret; ret = env_export(env_new); if (ret) return ret; if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { printf("\n** Cannot find mtd partition \"%s\"\n", CONFIG_ENV_UBI_PART); return 1; } if (gd->env_valid == ENV_VALID) { puts("Writing to redundant UBI... "); if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND, (void *)env_new, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND); return 1; } } else { puts("Writing to UBI... "); if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); return 1; } } puts("done\n"); gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND; return 0; } #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */ static int env_ubi_save(void) { ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); int ret; ret = env_export(env_new); if (ret) return ret; if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { printf("\n** Cannot find mtd partition \"%s\"\n", CONFIG_ENV_UBI_PART); return 1; } if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); return 1; } puts("done\n"); return 0; }
int saveenv(void) { ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); int ret; ret = env_export(env_new); if (ret) return ret; if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { printf("\n** Cannot find mtd partition \"%s\"\n", CONFIG_ENV_UBI_PART); return 1; } env_new->flags = ++env_flags; /* increase the serial */ if (gd->env_valid == 1) { puts("Writing to redundant UBI... "); if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND, (void *)env_new, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND); return 1; } } else { puts("Writing to UBI... "); if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); return 1; } } puts("done\n"); gd->env_valid = gd->env_valid == 2 ? 1 : 2; return 0; }
static int env_ubi_save(void) { ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); int ret; ret = env_export(env_new); if (ret) return ret; if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { printf("\n** Cannot find mtd partition \"%s\"\n", CONFIG_ENV_UBI_PART); return 1; } if (gd->env_valid == ENV_VALID) { puts("Writing to redundant UBI... "); if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND, (void *)env_new, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND); return 1; } } else { puts("Writing to UBI... "); if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); return 1; } } puts("done\n"); gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND; return 0; }
static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { size_t size = 0; ulong addr = 0; int err = 0; if (argc < 2) { cmd_usage(cmdtp); return 1; } if (strcmp(argv[1], "part") == 0) { /* Print current partition */ if (argc == 2) { if (ubi_dev.type == DEV_TYPE_NONE) { printf("Error, no UBI device/partition selected!\n"); return 1; } printf("%s Device %d: %s, partition %s\n", ubi_dev.dev_name, ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_name); return 0; } if (argc < 4) { cmd_usage(cmdtp); return 1; } /* todo: get dev number for NAND... */ ubi_dev.nr = 0; /* * Call ubi_exit() before re-initializing the UBI subsystem */ if (ubi_initialized) { ubi_exit(); del_mtd_partitions(ubi_dev.mtd_info); } /* * Check for nand|onenand selection */ #if defined(CONFIG_CMD_NAND) if (strcmp(argv[2], "nand") == 0) { strcpy(ubi_dev.dev_name, "NAND"); ubi_dev.type = DEV_TYPE_NAND; ubi_dev.mtd_info = &nand_info[ubi_dev.nr]; } #endif #if defined(CONFIG_FLASH_CFI_MTD) if (strcmp(argv[2], "nor") == 0) { strcpy(ubi_dev.dev_name, "NOR"); ubi_dev.type = DEV_TYPE_NOR; ubi_dev.mtd_info = get_mtd_device_nm(CFI_MTD_DEV_NAME); } #endif #if defined(CONFIG_CMD_ONENAND) if (strcmp(argv[2], "onenand") == 0) { strcpy(ubi_dev.dev_name, "OneNAND"); ubi_dev.type = DEV_TYPE_ONENAND; ubi_dev.mtd_info = &onenand_mtd; } #endif if (ubi_dev.type == DEV_TYPE_NONE) { printf("Error, no UBI device/partition selected!\n"); return 1; } strcpy(ubi_dev.part_name, argv[3]); err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name); if (err) { printf("UBI init error %d\n", err); ubi_dev.type = DEV_TYPE_NONE; return err; } ubi = ubi_devices[0]; return 0; } if ((strcmp(argv[1], "part") != 0) && (ubi_dev.type == DEV_TYPE_NONE)) { printf("Error, no UBI device/partition selected!\n"); return 1; } if (strcmp(argv[1], "info") == 0) { int layout = 0; if (argc > 2 && !strncmp(argv[2], "l", 1)) layout = 1; return ubi_info(layout); } if (strncmp(argv[1], "create", 6) == 0) { int dynamic = 1; /* default: dynamic volume */ /* Use maximum available size */ size = 0; /* E.g., create volume size type */ if (argc == 5) { if (strncmp(argv[4], "s", 1) == 0) dynamic = 0; else if (strncmp(argv[4], "d", 1) != 0) { printf("Incorrect type\n"); return 1; } argc--; } /* E.g., create volume size */ if (argc == 4) { size = simple_strtoul(argv[3], NULL, 16); argc--; } /* Use maximum available size */ if (!size) size = ubi->avail_pebs * ubi->leb_size; /* E.g., create volume */ if (argc == 3) return ubi_create_vol(argv[2], size, dynamic); } if (strncmp(argv[1], "remove", 6) == 0) { /* E.g., remove volume */ if (argc == 3) return ubi_remove_vol(argv[2]); } if (strncmp(argv[1], "write", 5) == 0) { if (argc < 5) { printf("Please see usage\n"); return 1; } addr = simple_strtoul(argv[2], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); return ubi_volume_write(argv[3], (void *)addr, size); } if (strncmp(argv[1], "read", 4) == 0) { size = 0; /* E.g., read volume size */ if (argc == 5) { size = simple_strtoul(argv[4], NULL, 16); argc--; } /* E.g., read volume */ if (argc == 4) { addr = simple_strtoul(argv[2], NULL, 16); argc--; } if (argc == 3) return ubi_volume_read(argv[3], (char *)addr, size); } printf("Please see usage\n"); return -1; }
int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { size_t size = 0; ulong addr = 0; int err = 0; size_t vol_offset = 0; if (argc < 2) { printf("Usage:\n%s\n", cmdtp->usage); return 1; } if (mtdparts_init() != 0) { printf("Error initializing mtdparts!\n"); return 1; } if (strcmp(argv[1], "part") == 0) { char mtd_dev[16]; struct mtd_device *dev; struct part_info *part; const char *vid_header_offset = NULL; u8 pnum; /* Print current partition */ if (argc == 2) { if (!ubi_dev.selected) { printf("Error, no UBI device/partition selected!\n"); return 1; } printf("Device %d: %s, partition %s\n", ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_name); return 0; } if (argc < 3) { printf("Usage:\n%s\n", cmdtp->usage); return 1; } /* todo: get dev number for NAND... */ ubi_dev.nr = 0; /* * Call ubi_exit() before re-initializing the UBI subsystem */ if (ubi_initialized) { ubi_exit(); del_mtd_partitions(ubi_dev.mtd_info); } /* * Search the mtd device number where this partition * is located */ if (find_dev_and_part(argv[2], &dev, &pnum, &part)) { printf("Partition %s not found!\n", argv[2]); return 1; } sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num); ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev); if (IS_ERR(ubi_dev.mtd_info)) { printf("Partition %s not found on device %s!\n", argv[2], mtd_dev); return 1; } ubi_dev.selected = 1; if (argc > 3) vid_header_offset = argv[3]; strcpy(ubi_dev.part_name, argv[2]); err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name, vid_header_offset); if (err) { printf("UBI init error %d\n", err); ubi_dev.selected = 0; return err; } ubi = ubi_devices[0]; return 0; } if (strcmp(argv[1], "detach") == 0) { if (ubi_initialized) { ubi_exit(); del_mtd_partitions(ubi_dev.mtd_info); ubi_initialized = 0; ubi_dev.selected = 0; if (ubi) memset(ubi, 0, sizeof(*ubi)); } return 0; } if ((strcmp(argv[1], "part") != 0) && (!ubi_dev.selected)) { printf("Error, no UBI device/partition selected!\n"); return 1; } if (strcmp(argv[1], "info") == 0) { int layout = 0; if (argc > 2 && !strncmp(argv[2], "l", 1)) layout = 1; if (argc > 2 && !strncmp(argv[2], "w", 1)) layout = 2; return ubi_info(layout); } if (strncmp(argv[1], "create", 6) == 0) { int dynamic = 1; /* default: dynamic volume */ /* Use maximum available size */ size = 0; /* E.g., create volume size type */ if (argc == 5) { if (strncmp(argv[4], "s", 1) == 0) dynamic = 0; else if (strncmp(argv[4], "d", 1) != 0) { printf("Incorrect type\n"); return 1; } argc--; } /* E.g., create volume size */ if (argc == 4) { size = simple_strtoul(argv[3], NULL, 16); argc--; } /* Use maximum available size */ if (!size) { if (ubi->avail_pebs < MIN_AVAILABLE_PEB) { ubi_err("available_pebs %d < MIN_AVAILABLE_PEB %d\n", ubi->avail_pebs, MIN_AVAILABLE_PEB); return 1; } size = (ubi->avail_pebs - MIN_AVAILABLE_PEB) * ubi->leb_size; printf("No size specified -> Using max size (0x%x)\n", size); } /* E.g., create volume */ if (argc == 3) return ubi_create_vol(argv[2], size, dynamic); } if (strncmp(argv[1], "remove", 6) == 0) { /* E.g., remove volume */ if (argc == 3) return ubi_remove_vol(argv[2]); } if (strncmp(argv[1], "write", 5) == 0) { if (argc < 5) { printf("Please see usage\n"); return 1; } addr = simple_strtoul(argv[2], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); return ubi_volume_write(argv[3], (void *)addr, size); } if (strncmp(argv[1], "read", 4) == 0) { size = 0; vol_offset = 0; /* E.g., offset in volume */ if (argc == 6) { vol_offset = simple_strtoul(argv[5], NULL, 16); argc--; } /* E.g., read volume size */ if (argc == 5) { size = simple_strtoul(argv[4], NULL, 16); argc--; } /* E.g., read volume */ if (argc == 4) { addr = simple_strtoul(argv[2], NULL, 16); argc--; } if (argc == 3) return ubi_volume_read(argv[3], (char *)addr, size, vol_offset); } printf("Please see usage\n"); return 1; }
static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int64_t size = 0; ulong addr = 0; if (argc < 2) return CMD_RET_USAGE; if (strcmp(argv[1], "detach") == 0) return ubi_detach(); if (strcmp(argv[1], "part") == 0) { const char *vid_header_offset = NULL; /* Print current partition */ if (argc == 2) { if (!ubi) { printf("Error, no UBI device selected!\n"); return 1; } printf("Device %d: %s, MTD partition %s\n", ubi->ubi_num, ubi->ubi_name, ubi->mtd->name); return 0; } if (argc < 3) return CMD_RET_USAGE; if (argc > 3) vid_header_offset = argv[3]; return ubi_part(argv[2], vid_header_offset); } if ((strcmp(argv[1], "part") != 0) && !ubi) { printf("Error, no UBI device selected!\n"); return 1; } if (strcmp(argv[1], "info") == 0) { int layout = 0; if (argc > 2 && !strncmp(argv[2], "l", 1)) layout = 1; return ubi_info(layout); } if (strcmp(argv[1], "check") == 0) { if (argc > 2) return ubi_check(argv[2]); printf("Error, no volume name passed\n"); return 1; } if (strncmp(argv[1], "create", 6) == 0) { int dynamic = 1; /* default: dynamic volume */ int id = UBI_VOL_NUM_AUTO; /* Use maximum available size */ size = 0; /* E.g., create volume size type vol_id */ if (argc == 6) { id = simple_strtoull(argv[5], NULL, 16); argc--; } /* E.g., create volume size type */ if (argc == 5) { if (strncmp(argv[4], "s", 1) == 0) dynamic = 0; else if (strncmp(argv[4], "d", 1) != 0) { printf("Incorrect type\n"); return 1; } argc--; } /* E.g., create volume size */ if (argc == 4) { if (argv[3][0] != '-') size = simple_strtoull(argv[3], NULL, 16); argc--; } /* Use maximum available size */ if (!size) { size = (int64_t)ubi->avail_pebs * ubi->leb_size; printf("No size specified -> Using max size (%lld)\n", size); } /* E.g., create volume */ if (argc == 3) return ubi_create_vol(argv[2], size, dynamic, id); } if (strncmp(argv[1], "remove", 6) == 0) { /* E.g., remove volume */ if (argc == 3) return ubi_remove_vol(argv[2]); } if (strncmp(argv[1], "write", 5) == 0) { int ret; if (argc < 5) { printf("Please see usage\n"); return 1; } addr = simple_strtoul(argv[2], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); if (strlen(argv[1]) == 10 && strncmp(argv[1] + 5, ".part", 5) == 0) { if (argc < 6) { ret = ubi_volume_continue_write(argv[3], (void *)addr, size); } else { size_t full_size; full_size = simple_strtoul(argv[5], NULL, 16); ret = ubi_volume_begin_write(argv[3], (void *)addr, size, full_size); } } else { ret = ubi_volume_write(argv[3], (void *)addr, size); } if (!ret) { printf("%lld bytes written to volume %s\n", size, argv[3]); } return ret; } if (strncmp(argv[1], "read", 4) == 0) { size = 0; /* E.g., read volume size */ if (argc == 5) { size = simple_strtoul(argv[4], NULL, 16); argc--; } /* E.g., read volume */ if (argc == 4) { addr = simple_strtoul(argv[2], NULL, 16); argc--; } if (argc == 3) { return ubi_volume_read(argv[3], (char *)addr, size); } } printf("Please see usage\n"); return 1; }
static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { size_t size = 0; ulong addr = 0; int err = 0; if (argc < 2) return CMD_RET_USAGE; if (mtdparts_init() != 0) { printf("Error initializing mtdparts!\n"); return 1; } if (strcmp(argv[1], "part") == 0) { char mtd_dev[16]; struct mtd_device *dev; struct part_info *part; const char *vid_header_offset = NULL; u8 pnum; /* Print current partition */ if (argc == 2) { if (!ubi_dev.selected) { printf("Error, no UBI device/partition selected!\n"); return 1; } printf("Device %d: %s, partition %s\n", ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_name); return 0; } if (argc < 3) return CMD_RET_USAGE; #ifdef CONFIG_CMD_UBIFS /* * Automatically unmount UBIFS partition when user * changes the UBI device. Otherwise the following * UBIFS commands will crash. */ if (ubifs_is_mounted()) cmd_ubifs_umount(); #endif /* todo: get dev number for NAND... */ ubi_dev.nr = 0; /* * Call ubi_exit() before re-initializing the UBI subsystem */ if (ubi_initialized) { ubi_exit(); del_mtd_partitions(ubi_dev.mtd_info); } /* * Search the mtd device number where this partition * is located */ if (find_dev_and_part(argv[2], &dev, &pnum, &part)) { printf("Partition %s not found!\n", argv[2]); return 1; } sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num); ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev); if (IS_ERR(ubi_dev.mtd_info)) { printf("Partition %s not found on device %s!\n", argv[2], mtd_dev); return 1; } ubi_dev.selected = 1; if (argc > 3) vid_header_offset = argv[3]; strcpy(ubi_dev.part_name, argv[2]); err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name, vid_header_offset); if (err) { printf("UBI init error %d\n", err); ubi_dev.selected = 0; return err; } ubi = ubi_devices[0]; return 0; } if ((strcmp(argv[1], "part") != 0) && (!ubi_dev.selected)) { printf("Error, no UBI device/partition selected!\n"); return 1; } if (strcmp(argv[1], "info") == 0) { int layout = 0; if (argc > 2 && !strncmp(argv[2], "l", 1)) layout = 1; return ubi_info(layout); } if (strncmp(argv[1], "create", 6) == 0) { int dynamic = 1; /* default: dynamic volume */ /* Use maximum available size */ size = 0; /* E.g., create volume size type */ if (argc == 5) { if (strncmp(argv[4], "s", 1) == 0) dynamic = 0; else if (strncmp(argv[4], "d", 1) != 0) { printf("Incorrect type\n"); return 1; } argc--; } /* E.g., create volume size */ if (argc == 4) { size = simple_strtoul(argv[3], NULL, 16); argc--; } /* Use maximum available size */ if (!size) { size = ubi->avail_pebs * ubi->leb_size; printf("No size specified -> Using max size (%u)\n", size); } /* E.g., create volume */ if (argc == 3) return ubi_create_vol(argv[2], size, dynamic); } if (strncmp(argv[1], "remove", 6) == 0) { /* E.g., remove volume */ if (argc == 3) return ubi_remove_vol(argv[2]); } if (strncmp(argv[1], "write", 5) == 0) { if (argc < 5) { printf("Please see usage\n"); return 1; } addr = simple_strtoul(argv[2], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); return ubi_volume_write(argv[3], (void *)addr, size); } if (strncmp(argv[1], "read", 4) == 0) { size = 0; /* E.g., read volume size */ if (argc == 5) { size = simple_strtoul(argv[4], NULL, 16); argc--; } /* E.g., read volume */ if (argc == 4) { addr = simple_strtoul(argv[2], NULL, 16); argc--; } if (argc == 3) return ubi_volume_read(argv[3], (char *)addr, size); } printf("Please see usage\n"); return 1; }
static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { size_t size = 0; ulong addr = 0; if (argc < 2) return CMD_RET_USAGE; if (strcmp(argv[1], "part") == 0) { const char *vid_header_offset = NULL; /* Print current partition */ if (argc == 2) { if (!ubi_dev.selected) { printf("Error, no UBI device/partition selected!\n"); return 1; } printf("Device %d: %s, partition %s\n", ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_name); return 0; } if (argc < 3) return CMD_RET_USAGE; if (argc > 3) vid_header_offset = argv[3]; return ubi_part(argv[2], vid_header_offset); } if ((strcmp(argv[1], "part") != 0) && (!ubi_dev.selected)) { printf("Error, no UBI device/partition selected!\n"); return 1; } if (strcmp(argv[1], "info") == 0) { int layout = 0; if (argc > 2 && !strncmp(argv[2], "l", 1)) layout = 1; return ubi_info(layout); } if (strncmp(argv[1], "create", 6) == 0) { int dynamic = 1; /* default: dynamic volume */ /* Use maximum available size */ size = 0; /* E.g., create volume size type */ if (argc == 5) { if (strncmp(argv[4], "s", 1) == 0) dynamic = 0; else if (strncmp(argv[4], "d", 1) != 0) { printf("Incorrect type\n"); return 1; } argc--; } /* E.g., create volume size */ if (argc == 4) { size = simple_strtoul(argv[3], NULL, 16); argc--; } /* Use maximum available size */ if (!size) { size = ubi->avail_pebs * ubi->leb_size; printf("No size specified -> Using max size (%u)\n", size); } /* E.g., create volume */ if (argc == 3) return ubi_create_vol(argv[2], size, dynamic); } if (strncmp(argv[1], "remove", 6) == 0) { /* E.g., remove volume */ if (argc == 3) return ubi_remove_vol(argv[2]); } if (strncmp(argv[1], "write", 5) == 0) { int ret; if (argc < 5) { printf("Please see usage\n"); return 1; } addr = simple_strtoul(argv[2], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); ret = ubi_volume_write(argv[3], (void *)addr, size); if (!ret) { printf("%d bytes written to volume %s\n", size, argv[3]); } return ret; } if (strncmp(argv[1], "read", 4) == 0) { size = 0; /* E.g., read volume size */ if (argc == 5) { size = simple_strtoul(argv[4], NULL, 16); argc--; } /* E.g., read volume */ if (argc == 4) { addr = simple_strtoul(argv[2], NULL, 16); argc--; } if (argc == 3) { printf("Read %d bytes from volume %s to %lx\n", size, argv[3], addr); return ubi_volume_read(argv[3], (char *)addr, size); } } printf("Please see usage\n"); return 1; }