/* * Read bootenv from ubi volume */ static int ubi_write_bootenv(uint32_t devno, uint32_t id, bootenv_t env) { libubi_t ulib; int rc = 0; char path[PATH_MAX]; FILE* fp_out = NULL; size_t nbytes; rc = bootenv_size(env, &nbytes); if (rc) { err_msg("Cannot determine size of bootenv structure\n"); return rc; } ulib = libubi_open(); if (ulib == NULL) { err_msg("Cannot allocate ubi structure\n"); return rc; } snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); fp_out = fopen(path, "r+"); if (fp_out == NULL) { err_msg("Cannot fopen volume:%d number:%d\n", devno, id); rc = -EBADF; goto err; } rc = ubi_update_start(ulib, fileno(fp_out), nbytes); if (rc != 0) { err_msg("Cannot start update for %s\n", path); goto err; } rc = bootenv_write(fp_out, env); if (rc != 0) { err_msg("Cannot write bootenv to volume %d number:%d\n", devno, id); goto err; } err: if( fp_out ) fclose(fp_out); libubi_close(ulib); return rc; }
/** * write_bootenv_volume - writes data from PFI file int to bootenv UBI volume * @devno UBI device number * @id UBI volume id * @bootend_old old PDD data from machine * @pdd_f function to handle PDD with * @fp_in new pdd data contained in PFI * @fp_in_size data size of new pdd data in PFI * @pfi_crc crc value from PFI header * * Error handling: * when UBI system couldn't be opened * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err * when bootenv can't be created * - returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err * when bootenv can't be read * - returns -PFIFLASH_ERR_BOOTENV_READ, err_buf matches text to err * when PDD handling function returns and error * - passes rc and err_buf data * when CRC check fails * - returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err * when bootenv can't be resized * - returns -PFIFLASH_ERR_BOOTENV_SIZE, 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 couldn't write bootenv data * - returns -PFIFLASH_ERR_BOOTENV_WRITE, err_buf matches text to err **/ static int write_bootenv_volume(int devno, uint32_t id, bootenv_t bootenv_old, pdd_func_t pdd_f, FILE* fp_in, size_t fp_in_size, uint32_t pfi_crc, char *err_buf, size_t err_buf_size) { int rc, warnings; uint32_t crc; size_t update_size; FILE *fp_out; bootenv_t bootenv_new, bootenv_res; ubi_lib_t ulib; rc = 0; warnings = 0; crc = 0; update_size = 0; fp_out = NULL; bootenv_new = NULL; bootenv_res = NULL; ulib = NULL; log_msg("[ ubiupdatevol bootenv id=%d, fp_in=%p", id, fp_in); /* Workflow: * 1. Apply PDD operation and get the size of the returning * bootenv_res section. Without the correct size it wouldn't * be possible to call UBI update vol. * 2. Call UBI update vol * 3. Get FILE* to vol dev * 4. Write to FILE* */ rc = ubi_open(&ulib); if (rc != 0) { rc = -PFIFLASH_ERR_UBI_OPEN; EBUF(PFIFLASH_ERRSTR[-rc]); goto err; } rc = bootenv_create(&bootenv_new); if (rc != 0) { rc = -PFIFLASH_ERR_BOOTENV_CREATE; EBUF(PFIFLASH_ERRSTR[-rc], " 'new'"); goto err; } rc = bootenv_create(&bootenv_res); if (rc != 0) { rc = -PFIFLASH_ERR_BOOTENV_CREATE; EBUF(PFIFLASH_ERRSTR[-rc], " 'res'"); goto err; } rc = bootenv_read_crc(fp_in, bootenv_new, fp_in_size, &crc); if (rc != 0) { rc = -PFIFLASH_ERR_BOOTENV_READ; EBUF(PFIFLASH_ERRSTR[-rc]); goto err; } else if (crc != pfi_crc) { rc = -PFIFLASH_ERR_CRC_CHECK; EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc); goto err; } rc = pdd_f(bootenv_old, bootenv_new, &bootenv_res, &warnings, err_buf, err_buf_size); if (rc != 0) { EBUF_PREPEND("handling PDD"); goto err; } else if (warnings) /* TODO do something with warnings */ dbg_msg("A warning in the PDD operation occured: %d", warnings); rc = bootenv_size(bootenv_res, &update_size); if (rc != 0) { rc = -PFIFLASH_ERR_BOOTENV_SIZE; 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; } rc = bootenv_write(fp_out, bootenv_res); if (rc != 0) { rc = -PFIFLASH_ERR_BOOTENV_WRITE; EBUF(PFIFLASH_ERRSTR[-rc], devno, id); goto err; } err: if (ulib != NULL) ubi_close(&ulib); if (bootenv_new != NULL) bootenv_destroy(&bootenv_new); if (bootenv_res != NULL) bootenv_destroy(&bootenv_res); if (fp_out) fclose(fp_out); return rc; }