Esempio n. 1
0
int
read_pdd_data(FILE* fp_pdd, pdd_data_t* pdd_data,
	      char* err_buf, size_t err_buf_size)
{
	int rc = 0;
	bootenv_t pdd = NULL;
	pdd_data_t res = NULL;
	const char* value;

	res = (pdd_data_t) malloc(sizeof(struct pdd_data));
	if (!res) {
		rc = -ENOMEM;
		goto err;
	}
	rc = bootenv_create(&pdd);
	if (rc != 0) {
		goto err;
	}
	rc = bootenv_read_txt(fp_pdd, pdd);
	if (rc != 0) {
		goto err;
	}
	rc = bootenv_get(pdd, "flash_type", &value);
	if (rc != 0) {
		goto err;
	}

	if (strcmp(value, "NAND") == 0) {

		rc = bootenv_get_num(pdd, "flash_page_size",
			     &(res->flash_page_size));
		if (rc != 0) {
			EBUF("Cannot read 'flash_page_size' from pdd.");
			goto err;
		}
		res->flash_type = NAND_FLASH;

		switch (res->flash_page_size) {
		case 512:
			res->vid_hdr_offset = NAND512_DEFAULT_VID_HDR_OFF;
			break;
		case 2048:
			res->vid_hdr_offset = NAND2048_DEFAULT_VID_HDR_OFF;
			break;
		default:
			EBUF("Unsupported  'flash_page_size' %d.",
			     res->flash_page_size);
			goto err;
		}
	}
	else if (strcmp(value, "NOR") == 0){
		res->flash_type = NOR_FLASH;
		res->vid_hdr_offset = NOR_DEFAULT_VID_HDR_OFF;
	}
	else {
		snprintf(err_buf, err_buf_size,
			 "Unkown flash type: %s", value);
		goto err;
	}

	rc = bootenv_get_num(pdd, "flash_eraseblock_size",
			     &(res->eb_size));
	if (rc != 0) {
		EBUF("Cannot read 'flash_eraseblock_size' from pdd.");
		goto err;
	}

	rc = bootenv_get_num(pdd, "flash_size",
			     &(res->flash_size));
	if (rc != 0) {
		EBUF("Cannot read 'flash_size' from pdd.");
		goto err;
	}

	goto out;
 err:
	if (res) {
		free(res);
		res = NULL;
	}
 out:
	bootenv_destroy(&pdd);
	*pdd_data = res;
	return rc;
}
int
main(int argc, char **argv) {
	int rc = 0;
	bootenv_t env = NULL;
	uint32_t boot_volno;
	myargs args = {
		.action = ACT_NORMAL,
		.file_in  = NULL,
		.file_out = NULL,
		.side = -1,
		.x86 = 0,
		.both = 0,
		.env_in = NULL,

		.arg1 = NULL,
		.options = NULL,
	};

	rc = bootenv_create(&env);
	if (rc != 0) {
		err_msg("Cannot create bootenv handle. rc: %d", rc);
		goto err;
	}

	rc = bootenv_create(&(args.env_in));
	if (rc != 0) {
		err_msg("Cannot create bootenv handle. rc: %d", rc);
		goto err;
	}

	parse_opt(argc, argv, &args);
	if (args.action == ACT_ARGP_ERR) {
		rc = -1;
		goto err;
	}
	if (args.action == ACT_ARGP_ABORT) {
		rc = 0;
		goto out;
	}

	if ((args.side == 0) || (args.side == -1))
		boot_volno = EXAMPLE_BOOTENV_VOL_ID_1;
	else
		boot_volno = EXAMPLE_BOOTENV_VOL_ID_2;

	if( args.x86 )
		rc = read_bootenv(args.file_in, env);
	else
		rc = ubi_read_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env);
	if (rc != 0) {
		goto err;
	}

	if (args.action == ACT_LIST) {
		rc = list_bootenv(env);
		if (rc != 0) {
			goto err;
		}
		goto out;
	}

	rc = process_key_value(args.env_in, env);
	if (rc != 0) {
		goto err;
	}

	if( args.x86 )
		rc = write_bootenv(args.file_in, env);
	else
		rc = ubi_write_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env);
	if (rc != 0)
		goto err;

	if( args.both )		/* No side specified, update both */
		rc = do_mirror(boot_volno);

 out:
 err:
	bootenv_destroy(&env);
	bootenv_destroy(&(args.env_in));
	return rc;
}
Esempio n. 3
0
/**
 * 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;
}
Esempio n. 4
0
static int compare_bootenv(FILE *fp_pfi, FILE **fp_flash, uint32_t ids_size,
		uint32_t data_size, pdd_func_t pdd_f, char *err_buf,
		size_t err_buf_size)
{
	int rc, warnings = 0;
	unsigned int i;
	bootenv_t bootenv_pfi, bootenv_res = NULL, bootenv_flash = NULL;

	rc = bootenv_create(&bootenv_pfi);
	if (rc != 0) {
		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
		goto err;
	}

	rc = bootenv_create(&bootenv_res);
	if (rc != 0) {
		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
		goto err;
	}

	rc = bootenv_read(fp_pfi, bootenv_pfi, data_size);
	if (rc != 0) {
		rc = -PFIFLASH_ERR_BOOTENV_READ;
		goto err;
	}

	for (i = 0; i < ids_size; i++) {
		rc = bootenv_create(&bootenv_flash);
		if (rc != 0) {
			rc = -PFIFLASH_ERR_BOOTENV_CREATE;
			goto err;
		}

		rc = bootenv_read(fp_flash[i], bootenv_flash, BOOTENV_MAXSIZE);
		if (rc != 0) {
			rc = -PFIFLASH_ERR_BOOTENV_READ;
			goto err;
		}

		rc = pdd_f(bootenv_flash, bootenv_pfi, &bootenv_res,
				&warnings, err_buf, err_buf_size);
		if (rc != 0) {
			rc = -PFIFLASH_ERR_PDD_UNKNOWN;
			goto err;
		}

		rc = bootenv_compare(bootenv_flash, bootenv_res);
		if (rc > 0) {
			rc = -PFIFLASH_CMP_DIFF;
			goto err;
		} else if (rc < 0) {
			rc = -PFIFLASH_ERR_COMPARE;
			goto err;
		}

		bootenv_destroy(&bootenv_flash);
		bootenv_flash = NULL;
	}

err:
	if (bootenv_pfi)
		bootenv_destroy(&bootenv_pfi);
	if (bootenv_res)
		bootenv_destroy(&bootenv_res);
	if (bootenv_flash)
		bootenv_destroy(&bootenv_flash);

	return rc;
}
Esempio n. 5
0
/**
 * pfiflash_with_options - exposed func to flash memory with a PFI file
 * @pfi			PFI data file pointer
 * @complete		flag to erase unmapped volumes
 * @seqnum		sequence number
 * @compare		flag to compare
 * @pdd_handling	method to handle pdd (keep, merge, overwrite...)
 *
 * Error handling:
 *	when bootenv can't be created
 *	- returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err
 *	when PFI headers can't be read, or
 *	when fail to skip raw sections, or
 *	when error occurs while processing raw volumes, or
 *	when fail to erase unmapped UBI vols, or
 *	when error occurs while processing UBI volumes, or
 *	when error occurs while mirroring UBI volumes
 *	- passes rc, prepends err_buf with contextual aid
 **/
int
pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare,
		  pdd_handling_t pdd_handling, const char* rawdev,
		  char *err_buf, size_t err_buf_size)
{
	int rc;
	bootenv_t bootenv;
	pdd_func_t pdd_f;

	if (pfi == NULL)
		return -EINVAL;

	rc = 0;
	pdd_f = NULL;

	/* If the user didnt specify a seqnum we start per default
	 * with the index 0 */
	int curr_seqnum = seqnum < 0 ? 0 : seqnum;

	list_t pfi_raws   = mk_empty(); /* list of raw sections from a pfi */
	list_t pfi_ubis   = mk_empty(); /* list of ubi sections from a pfi */

	rc = bootenv_create(&bootenv);
	if (rc != 0) {
		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
		EBUF(PFIFLASH_ERRSTR[-rc], "");
		goto err;
	}

	rc = read_pfi_headers(&pfi_raws, &pfi_ubis, pfi, err_buf, err_buf_size);
	if (rc != 0) {
		EBUF_PREPEND("reading PFI header");
		goto err;
	}

	if (rawdev == NULL || compare)
		rc = skip_raw_volumes(pfi, pfi_raws, err_buf, err_buf_size);
	else
		rc = process_raw_volumes(pfi, pfi_raws, rawdev, err_buf,
					 err_buf_size);
	if (rc != 0) {
		EBUF_PREPEND("handling raw section");
		goto err;
	}

	if (complete && !compare) {
		rc = erase_unmapped_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis,
						err_buf, err_buf_size);
		if (rc != 0) {
			EBUF_PREPEND("deleting unmapped UBI volumes");
			goto err;
		}
	}

	if (((int)pdd_handling >= 0) &&
	    (pdd_handling < PDD_HANDLING_NUM))
		pdd_f = pdd_funcs[pdd_handling];
	else {
		rc = -PFIFLASH_ERR_PDD_UNKNOWN;
		EBUF(PFIFLASH_ERRSTR[-rc]);
		goto err;
	}

	if (!compare) {
		rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv,
				pdd_f, UBI_REMOVE, err_buf, err_buf_size);
		if (rc != 0) {
			EBUF_PREPEND("removing UBI volumes");
			goto err;
		}

		rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv,
				pdd_f, UBI_WRITE, err_buf, err_buf_size);
		if  (rc != 0) {
			EBUF_PREPEND("writing UBI volumes");
			goto err;
		}

		if (seqnum < 0) { /* mirror redundant pairs */
			rc = mirror_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis,
					err_buf, err_buf_size);
			if (rc != 0) {
				EBUF_PREPEND("mirroring UBI volumes");
				goto err;
			}
		}
	} else {
		/* only compare volumes, don't alter the content */
		rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv,
				pdd_f, UBI_COMPARE, err_buf, err_buf_size);

		if (rc == -PFIFLASH_CMP_DIFF)
			/* update is necessary, return positive value */
			rc = 1;

		if (rc < 0) {
			EBUF_PREPEND("comparing UBI volumes");
			goto err;
		}
	}

 err:
	pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws);
	pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis);
	bootenv_destroy(&bootenv);
	return rc;
}