int ubi_volume_begin_write(char *volume, void *buf, size_t size, size_t full_size) { int err = 1; int rsvd_bytes = 0; struct ubi_volume *vol; vol = ubi_find_volume(volume); if (vol == NULL) return ENODEV; rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); if (size > rsvd_bytes) { printf("size > volume size! Aborting!\n"); return EINVAL; } err = ubi_start_update(ubi, vol, full_size); if (err < 0) { printf("Cannot start volume update\n"); return -err; } return ubi_volume_continue_write(volume, buf, size); }
static int ubi_volume_continue_write(char *volume, void *buf, size_t size) { int err = 1; struct ubi_volume *vol; vol = ubi_find_volume(volume); if (vol == NULL) return ENODEV; err = ubi_more_update_data(ubi, vol, buf, size); if (err < 0) { printf("Couldnt or partially wrote data\n"); return -err; } if (err) { size = err; err = ubi_check_volume(ubi, vol->vol_id); if (err < 0) return -err; if (err) { ubi_warn(ubi, "volume %d on UBI device %d is corrupt", vol->vol_id, ubi->ubi_num); vol->corrupted = 1; } vol->checked = 1; ubi_gluebi_updated(vol); } return 0; }
static int ubi_remove_vol(char *volume) { int err, reserved_pebs, i; struct ubi_volume *vol; vol = ubi_find_volume(volume); if (vol == NULL) return ENODEV; if (!strncmp(vol->name, "Factory", 7)) { printf("Remove volume %s is inhibited\n", vol->name); return EROFS; } printf("Remove UBI volume %s (id %d)\n", vol->name, vol->vol_id); if (ubi->ro_mode) { printf("It's read-only mode\n"); err = EROFS; goto out_err; } err = ubi_change_vtbl_record(ubi, vol->vol_id, NULL); if (err) { printf("Error changing Vol tabel record err=%x\n", err); goto out_err; } reserved_pebs = vol->reserved_pebs; for (i = 0; i < vol->reserved_pebs; i++) { err = ubi_eba_unmap_leb(ubi, vol, i); if (err) goto out_err; } kfree(vol->eba_tbl); ubi->volumes[vol->vol_id]->eba_tbl = NULL; ubi->volumes[vol->vol_id] = NULL; ubi->rsvd_pebs -= reserved_pebs; ubi->avail_pebs += reserved_pebs; i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs; if (i > 0) { i = ubi->avail_pebs >= i ? i : ubi->avail_pebs; ubi->avail_pebs -= i; ubi->rsvd_pebs += i; ubi->beb_rsvd_pebs += i; if (i > 0) ubi_msg("reserve more %d PEBs", i); } ubi->vol_count -= 1; return 0; out_err: ubi_err("cannot remove volume %s, error %d", volume, err); if (err < 0) err = -err; return err; }
static int ubi_volume_write(char *volume, void *buf, size_t size) { int err = 1; int rsvd_bytes = 0; struct ubi_volume *vol; vol = ubi_find_volume(volume); if (vol == NULL) return ENODEV; rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); if (size < 0 || size > rsvd_bytes) { printf("size > volume size! Aborting!\n"); return EINVAL; } if (!strncmp(vol->name, "Factory", 7) && (!size || size != rsvd_bytes)) { printf("Partial write to volume %s is inhibited\n", vol->name); return EROFS; } err = ubi_start_update(ubi, vol, size); if (err < 0) { printf("Cannot start volume update\n"); return -err; } err = ubi_more_update_data(ubi, vol, buf, size); if (err < 0) { printf("Couldnt or partially wrote data\n"); return -err; } if (err) { size = err; err = ubi_check_volume(ubi, vol->vol_id); if (err < 0) return -err; if (err) { ubi_warn("volume %d on UBI device %d is corrupted", vol->vol_id, ubi->ubi_num); vol->corrupted = 1; } vol->checked = 1; ubi_gluebi_updated(vol); } printf("\n0x%x bytes written to volume %s\n", size, volume); return 0; }
static int ubi_volume_read(char *volume, char *buf, size_t size, size_t offset) { int err, lnum, off, len, tbuf_size; void *tbuf; unsigned long long tmp; struct ubi_volume *vol; loff_t offp = 0; vol = ubi_find_volume(volume); if (vol == NULL) return ENODEV; offp = offset; printf("Read 0x%x bytes from volume [%s] offset 0x%x to %p\n", size, volume, offset, buf); if (vol->updating) { printf("updating"); return EBUSY; } if (vol->upd_marker) { printf("damaged volume, update marker is set"); return EBADF; } if (offp == vol->used_bytes) return 0; if (size == 0) { printf("No size specified -> Using max size (0x%lx)\n", (long)vol->used_bytes); size = vol->used_bytes; } if (vol->corrupted) printf("read from corrupted volume %d", vol->vol_id); if (offp + size > vol->used_bytes) size = vol->used_bytes - offp; tbuf_size = vol->usable_leb_size; if (size < tbuf_size) tbuf_size = ALIGN(size, ubi->min_io_size); tbuf = malloc(tbuf_size); if (!tbuf) { printf("NO MEM\n"); return ENOMEM; } len = size > tbuf_size ? tbuf_size : size; tmp = offp; off = do_div(tmp, vol->usable_leb_size); lnum = tmp; do { if (off + len >= vol->usable_leb_size) len = vol->usable_leb_size - off; err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0); if (err) { printf("read err %x\n", err); err = -err; break; } off += len; if (off == vol->usable_leb_size) { lnum += 1; off -= vol->usable_leb_size; } size -= len; offp += len; memcpy(buf, tbuf, len); buf += len; len = size > tbuf_size ? tbuf_size : size; } while (size); free(tbuf); debug("\n0x%x bytes read from volume %s\n", size, volume); return err; }
void env_relocate_spec (void) { #if defined(CONFIG_CMD_UBI) #if !defined(ENV_IS_EMBEDDED) int ret, i, readfrombackup; char cmd_buf[30]; struct mtd_device *dev; struct part_info *part; uint32_t crc; size_t size; env_t *ep; u8 pnum; #if defined(CONFIG_ENV_OFFSET_OOB) ret = get_nand_env_oob(&nand_info[0], &nand_env_oob_offset); /* * If unable to read environment offset from NAND OOB then fall through * to the normal environment reading code below */ if (!ret) { printf("Found Environment offset in OOB..\n"); } else { set_default_env("!no env offset in OOB"); return; } #endif //get mtdpart string from pni set_default_env("!set default for mtdparts"); #if (ENABLE_MODULE_NAND_FLASH == 1) drvNAND_GetMtdParts(mtdstr); #endif #if (ENABLE_MODULE_SPI_NAND_FLASH == 1) MDrv_SPINAND_GetMtdParts(mtdstr); #endif setenv("mtdparts", mtdstr); setenv("mtdids", IdsStr); mtdparts_init(); if(find_dev_and_part(env_partition, &dev, &pnum, &part)) { printf("Partition %s not found!\n", env_partition); printf("read env fail\n"); return; } if(!ubi_find_volume(ENV_VOL_NAME)) { sprintf(cmd_buf, "ubi part %s", env_partition); if(run_command(cmd_buf, 0) == -1) return; } if(!ubi_leb_sz) ubi_leb_sz = ubi_get_leb_size(); if(!env_vol_sz) env_vol_sz = (ubi_get_avai_peb() - 1) * ubi_leb_sz; if(cfg_env_offset == 0) { MsApiChunkHeader_GetValue(CH_UBOOT_ENVIRONMENT_ROM_OFFSET,&cfg_env_offset); ubi_get_volume_size(ENV_VOL_NAME, &size); cfg_env_offset = size - (cfg_env_offset*ubi_leb_sz); } //find ENV volume readfrombackup = 0; if(ubi_find_volume(ENV_VOL_NAME)) { for(i = 0 ;i < CONFIG_ENV_BLOCK_NUM; i ++) { ret = readenv(CONFIG_ENV_OFFSET + i * ubi_leb_sz, (u_char *)gbuf); if (ret) { if(i < (CONFIG_ENV_BLOCK_NUM - 1)) { printf("Read ENV fail, Read Backup ENV\n"); readfrombackup = 1; continue; } else { printf("Read Backup ENV Failed\n"); return; } } ep = (env_t*) gbuf; memcpy(&crc, &ep->crc, sizeof(crc)); // printf("Calc crc %X, Read crc %X\n", crc32(0, ep->data, ENV_SIZE), crc); if(crc32_env_ubi(0, ep->data, ENV_SIZE) == crc) { env_import(gbuf, 0); break; } else { if(i < (CONFIG_ENV_BLOCK_NUM - 1)) { printf("Read ENV crc error, Read Backup ENV\n"); readfrombackup = 1; } else { printf("Read Backup ENV crc error\n"); return; } } } } else { printf("Found no %s Volume\n Create %s volume\n", ENV_VOL_NAME, ENV_VOL_NAME); ret = ubi_create_vol(ENV_VOL_NAME, env_vol_sz, 1); if(ret) printf("create %s volume in %s partition fail with size = 0x%X\n", ENV_VOL_NAME, env_partition, env_vol_sz); ubi_leb_sz = ubi_get_leb_size(); ubi_get_volume_size(ENV_VOL_NAME, &size); MsApiChunkHeader_GetValue(CH_UBOOT_ENVIRONMENT_ROM_OFFSET,&cfg_env_offset); cfg_env_offset = size - (cfg_env_offset*ubi_leb_sz); } //restore data from backup if(readfrombackup == 1) { ret = saveenv(); if(ret) printf("restore data fail\n"); } #endif /* ! ENV_IS_EMBEDDED */ #else set_default_env("!set default for NAND program"); #endif /* ! CONFIG_CMD_UBI*/ }
int saveenv(void) { #if defined(CONFIG_CMD_UBI) int ret; char cmd_buf[30]; ssize_t len; size_t size; char *res; struct mtd_device *dev; struct part_info *part; char last_ubi_partname[32]; char last_sb_name[32]; u8 pnum; memset(last_ubi_partname, 0, 32); memset(last_sb_name, 0, 32); ubi_get_part_name(last_ubi_partname); ubifs_get_sb_name(last_sb_name); if(find_dev_and_part(env_partition, &dev, &pnum, &part)) { printf("Partition %s not found!\n", env_partition); printf("save env fail\n"); return 1; } if(!ubi_find_volume(ENV_VOL_NAME)) { sprintf(cmd_buf, "ubi part %s", env_partition); if(run_command(cmd_buf, 0) == -1) return 1; } if(!ubi_leb_sz) ubi_leb_sz = ubi_get_leb_size(); res = (char *)&env_new.data; len = hexport_r(&env_htab, '\0', &res, ENV_SIZE); if (len < 0) { printf("Cannot export environment\n"); return 1; } env_new.crc = crc32_env_ubi(0, env_new.data, ENV_SIZE); //printf("saveenv crc = %X\n", env_new.crc); if(ubi_find_volume(ENV_VOL_NAME)) { printf("Write Env to %X...\n", CONFIG_ENV_OFFSET); ret = writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new); if (ret) { puts("Failed\n"); return ret; } printf("Write Backup Env to %X...\n", CONFIG_ENV_OFFSET + ubi_leb_sz); ret = writeenv(CONFIG_ENV_OFFSET + ubi_leb_sz, (u_char *) &env_new); if (ret) { puts("Backup Failed\n"); return ret; } } else { printf("Found no %s Volume\n Create %s volume\n", ENV_VOL_NAME, ENV_VOL_NAME); ret = ubi_create_vol(ENV_VOL_NAME, env_vol_sz, 1); if(ret) { printf("create %s volume in %s partition fail with size = %0xX\n", ENV_VOL_NAME, env_partition, env_vol_sz); return ret; } ubi_leb_sz = ubi_get_leb_size(); MsApiChunkHeader_GetValue(CH_UBOOT_ENVIRONMENT_ROM_OFFSET,&cfg_env_offset); ubi_get_volume_size(ENV_VOL_NAME, &size); cfg_env_offset = size - (cfg_env_offset*ubi_leb_sz); ret = writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new); if (ret) { puts("Failed\n"); return ret; } ret = writeenv(CONFIG_ENV_OFFSET + ubi_leb_sz, (u_char *) &env_new); if (ret) { puts("Backup Failed\n"); return ret; } } if(last_ubi_partname[0]){ sprintf(cmd_buf, "ubi part %s", last_ubi_partname); if(run_command(cmd_buf, 0) == -1){ printf("restore ubi part %s failed\n", last_ubi_partname); return -1; } } if(last_sb_name[0]){ sprintf(cmd_buf, "ubifsmount %s", last_sb_name); if(run_command(cmd_buf, 0) == -1){ printf("remount volume %s failed\n", last_sb_name); return -1; } } puts("done\n"); return ret; #else return 0; #endif }