int ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes, const char* vol_name, struct ubi_vol_tbl_record *lvol_rec) { uint32_t crc; if ((u == NULL) || (vol_name == NULL)) return -EINVAL; memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE); lvol_rec->reserved_pebs = cpu_to_ubi32(byte_to_blk(reserved_bytes, u->leb_size)); lvol_rec->alignment = cpu_to_ubi32(u->alignment); lvol_rec->data_pad = u->v->data_pad; lvol_rec->vol_type = u->v->vol_type; lvol_rec->name_len = cpu_to_ubi16((uint16_t)strlen((const char*)vol_name)); memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1); crc = clc_crc32(crc32_table, UBI_CRC32_INIT, lvol_rec, UBI_VTBL_RECORD_SIZE_CRC); lvol_rec->crc = cpu_to_ubi32(crc); return 0; }
static void write_vid_hdr(ubi_info_t u, ubigen_action_t action) { uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, u->v, UBI_VID_HDR_SIZE_CRC); /* Write VID header */ u->v->hdr_crc = cpu_to_ubi32(crc); if (action & BROKEN_HDR_CRC) { u->v->hdr_crc = cpu_to_ubi32(ubi32_to_cpu(u->v->hdr_crc) + 1); } memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE); }
static void add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action) { uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, u->ptr_data, data_size); u->v->data_size = cpu_to_ubi32(data_size); u->v->data_crc = cpu_to_ubi32(crc); if (action & BROKEN_DATA_CRC) { u->v->data_crc = cpu_to_ubi32(ubi32_to_cpu(u->v->data_crc) + 1); } if (action & BROKEN_DATA_SIZE) { u->v->data_size = cpu_to_ubi32(ubi32_to_cpu(u->v->data_size) + 1); } }
static int init_vol_tab(struct ubi_vtbl_record **vol_tab, size_t *vol_tab_size) { uint32_t crc; size_t i; struct ubi_vtbl_record* res = NULL; *vol_tab_size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE; res = (struct ubi_vtbl_record*) calloc(1, *vol_tab_size); if (vol_tab == NULL) { return -ENOMEM; } for (i = 0; i < UBI_MAX_VOLUMES; i++) { crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(res[i]), UBI_VTBL_RECORD_SIZE_CRC); res[i].crc = cpu_to_be32(crc); } *vol_tab = res; return 0; }
int ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type, uint32_t eb_size, uint64_t ec, uint32_t alignment, uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag, size_t data_size, FILE* fp_in, FILE* fp_out) { int rc = 0; ubi_info_t res = NULL; uint32_t crc; uint32_t data_offset; if (alignment == 0) { rc = EUBIGEN_INVALID_ALIGNMENT; goto ubigen_create_err; } if ((fp_in == NULL) || (fp_out == NULL)) { rc = -EINVAL; goto ubigen_create_err; } res = (ubi_info_t) calloc(1, sizeof(struct ubi_info)); if (res == NULL) { rc = -ENOMEM; goto ubigen_create_err; } res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr)); if (res->v == NULL) { rc = -ENOMEM; goto ubigen_create_err; } res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr)); if (res->ec == NULL) { rc = -ENOMEM; goto ubigen_create_err; } /* data which is needed in the general process */ vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET; data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE; res->bytes_total = data_size; res->eb_size = eb_size ? eb_size : DEFAULT_BLOCKSIZE; res->data_pad = (res->eb_size - data_offset) % alignment; res->leb_size = res->eb_size - data_offset - res->data_pad; res->leb_total = byte_to_blk(data_size, res->leb_size); res->alignment = alignment; if ((res->eb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) { rc = EUBIGEN_TOO_SMALL_EB; goto ubigen_create_err; } res->fp_in = fp_in; res->fp_out = fp_out; /* vid hdr data which doesn't change */ res->v->magic = cpu_to_ubi32(UBI_VID_HDR_MAGIC); res->v->version = version ? version : UBI_VERSION; res->v->vol_type = vol_type; res->v->vol_id = cpu_to_ubi32(vol_id); res->v->compat = compat_flag; res->v->data_pad = cpu_to_ubi32(res->data_pad); /* static only: used_ebs */ if (res->v->vol_type == UBI_VID_STATIC) { res->v->used_ebs = cpu_to_ubi32(byte_to_blk (res->bytes_total, res->leb_size)); } /* ec hdr (fixed, doesn't change) */ res->ec->magic = cpu_to_ubi32(UBI_EC_HDR_MAGIC); res->ec->version = version ? version : UBI_VERSION; res->ec->ec = cpu_to_ubi64(ec); res->ec->vid_hdr_offset = cpu_to_ubi32(vid_hdr_offset); res->ec->data_offset = cpu_to_ubi32(data_offset); crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec, UBI_EC_HDR_SIZE_CRC); res->ec->hdr_crc = cpu_to_ubi32(crc); /* prepare a read buffer */ res->buf = (uint8_t*) malloc (res->eb_size * sizeof(uint8_t)); if (res->buf == NULL) { rc = -ENOMEM; goto ubigen_create_err; } /* point to distinct regions within the buffer */ res->ptr_ec_hdr = res->buf; res->ptr_vid_hdr = res->buf + ubi32_to_cpu(res->ec->vid_hdr_offset); res->ptr_data = res->buf + ubi32_to_cpu(res->ec->vid_hdr_offset) + UBI_VID_HDR_SIZE; rc = validate_ubi_info(res); if (rc != 0) { fprintf(stderr, "Volume validation failed: %d\n", rc); goto ubigen_create_err; } dump_info(res); *u = res; return rc; ubigen_create_err: if (res) { if (res->v) free(res->v); if (res->ec) free(res->ec); if (res->buf) free(res->buf); free(res); } *u = NULL; return rc; }
/** * process_raw_volumes - writes the raw sections of the PFI data * @pfi PFI data file pointer * @pfi_raws list of PFI raw headers * @rawdev device to use to write raw data * * Error handling: * when early EOF in PFI data * - returns -PFIFLASH_ERR_EOF, err_buf matches text to err * when file I/O error * - returns -PFIFLASH_ERR_FIO, err_buf matches text to err * when CRC check fails * - returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err * when opening MTD device fails * - reutrns -PFIFLASH_ERR_MTD_OPEN, err_buf matches text to err * when closing MTD device fails * - returns -PFIFLASH_ERR_MTD_CLOSE, err_buf matches text to err **/ static int process_raw_volumes(FILE* pfi, list_t pfi_raws, const char* rawdev, char* err_buf, size_t err_buf_size) { int rc; char *pfi_data; void *i; uint32_t crc, crc32_table[256]; size_t j, k; FILE* mtd = NULL; list_t ptr; if (is_empty(pfi_raws)) return 0; if (rawdev == NULL) return 0; rc = 0; pfi_data = NULL; log_msg("[ rawupdate dev=%s", rawdev); crc = UBI_CRC32_INIT; init_crc32_table(crc32_table); /* most likely only one element in list, but just in case */ foreach(i, ptr, pfi_raws) { pfi_raw_t r = (pfi_raw_t)i; /* read in pfi data */ if (pfi_data != NULL) free(pfi_data); pfi_data = malloc(r->data_size * sizeof(char)); for (j = 0; j < r->data_size; j++) { int c = fgetc(pfi); if (c == EOF) { rc = -PFIFLASH_ERR_EOF; EBUF(PFIFLASH_ERRSTR[-rc]); goto err; } else if (ferror(pfi)) { rc = -PFIFLASH_ERR_FIO; EBUF(PFIFLASH_ERRSTR[-rc]); goto err; } pfi_data[j] = (char)c; } crc = clc_crc32(crc32_table, crc, pfi_data, r->data_size); /* check crc */ if (crc != r->crc) { rc = -PFIFLASH_ERR_CRC_CHECK; EBUF(PFIFLASH_ERRSTR[-rc], r->crc, crc); goto err; } /* open device */ mtd = fopen(rawdev, "r+"); if (mtd == NULL) { rc = -PFIFLASH_ERR_MTD_OPEN; EBUF(PFIFLASH_ERRSTR[-rc], rawdev); goto err; } for (j = 0; j < r->starts_size; j++) { rc = erase_mtd_region(mtd, r->starts[j], r->data_size); if (rc) { EBUF(PFIFLASH_ERRSTR[-rc]); goto err; } fseek(mtd, r->starts[j], SEEK_SET); for (k = 0; k < r->data_size; k++) { int c = fputc((int)pfi_data[k], mtd); if (c == EOF) { fclose(mtd); rc = -PFIFLASH_ERR_EOF; EBUF(PFIFLASH_ERRSTR[-rc]); goto err; } if ((char)c != pfi_data[k]) { fclose(mtd); rc = -1; goto err; } } } rc = fclose(mtd); mtd = NULL; if (rc != 0) { rc = -PFIFLASH_ERR_MTD_CLOSE; EBUF(PFIFLASH_ERRSTR[-rc], rawdev); goto err; } }
/** * write_normal_volume - writes data from PFI file int to regular UBI volume * @devno UBI device number * @id UBI volume id * @update_size size of data stream * @fp_in PFI data file pointer * @pfi_crc CRC data from PFI header * * Error handling: * when UBI system couldn't be opened * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err * when UBI system couldn't open a volume * - returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err * when unexpected EOF is encountered * - returns -PFIFLASH_ERR_EOF, err_buf matches text to err * when file I/O error * - returns -PFIFLASH_ERR_FIO, err_buf matches text to err * when CRC check fails * - retruns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err **/ static int write_normal_volume(int devno, uint32_t id, size_t update_size, FILE* fp_in, uint32_t pfi_crc, char *err_buf, size_t err_buf_size) { int rc; uint32_t crc, crc32_table[256]; size_t bytes_left; FILE* fp_out; ubi_lib_t ulib; rc = 0; crc = UBI_CRC32_INIT; bytes_left = update_size; fp_out = NULL; ulib = NULL; log_msg("[ ubiupdatevol id=%d, update_size=%d fp_in=%p", id, update_size, fp_in); rc = ubi_open(&ulib); if (rc != 0) { rc = -PFIFLASH_ERR_UBI_OPEN; EBUF(PFIFLASH_ERRSTR[-rc]); goto err; } fp_out = ubi_vol_fopen_update(ulib, devno, id, update_size); if (!fp_out) { rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; EBUF(PFIFLASH_ERRSTR[-rc], id); goto err; } init_crc32_table(crc32_table); while (bytes_left) { char buf[1024]; size_t to_rw = sizeof buf > bytes_left ? bytes_left : sizeof buf; if (fread(buf, 1, to_rw, fp_in) != to_rw) { rc = -PFIFLASH_ERR_EOF; EBUF(PFIFLASH_ERRSTR[-rc]); goto err; } crc = clc_crc32(crc32_table, crc, buf, to_rw); if (fwrite(buf, 1, to_rw, fp_out) != to_rw) { rc = -PFIFLASH_ERR_FIO; EBUF(PFIFLASH_ERRSTR[-rc]); goto err; } bytes_left -= to_rw; } if (crc != pfi_crc) { rc = -PFIFLASH_ERR_CRC_CHECK; EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc); goto err; } err: if (fp_out) fclose(fp_out); if (ulib) ubi_close(&ulib); return rc; }