Beispiel #1
0
enum sh_css_err
sh_css_load_firmware(const char *fw_data,
		     unsigned int fw_size)
{
	int i, num_binaries;
	struct sh_css_fw_bi_h *binaries;
	struct sh_css_fw_bi_file_h *file_header;

	file_header = (struct sh_css_fw_bi_file_h *)fw_data;
	binaries = (struct sh_css_fw_bi_h *)(&file_header[1]);

	/* some sanity checks */
	if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h))
		return sh_css_err_internal_error;

	if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h))
		return sh_css_err_internal_error;

	num_binaries = file_header->binary_nr;

	for (i = 0; i < num_binaries; i++) {
		struct sh_css_fw_bi_h *bi = &binaries[i];

		/* sanity check */
		if (bi->size != bi->text_size + bi->data_size)
			return sh_css_err_internal_error;

		if (bi->offset + bi->size > fw_size)
			return sh_css_err_internal_error;

		if (bi->id == 0) {
			setup_sp(bi, fw_data);
		} else if (bi->id > 0) {
			const unsigned char *blob =
				(const unsigned char *)fw_data + bi->offset;
			sh_css_blob_info[bi->id-1].blob = blob;
			sh_css_blob_info[bi->id-1].size = bi->size;
		}
	}
	return sh_css_success;
}
enum ia_css_err
sh_css_load_firmware(const char *fw_data,
		     unsigned int fw_size)
{
	unsigned i;
	struct ia_css_fw_info *binaries;
	struct sh_css_fw_bi_file_h *file_header;
	bool valid_firmware = false;

	firmware_header = (struct firmware_header *)fw_data;
	file_header = (struct sh_css_fw_bi_file_h *)&firmware_header->file_header;
	binaries = (struct ia_css_fw_info *)&firmware_header->binary_header;
	strncpy(FW_rel_ver_name, file_header->version, min(sizeof(FW_rel_ver_name), sizeof(file_header->version)) - 1);
	valid_firmware = sh_css_check_firmware_version(fw_data);
	if (!valid_firmware) {
#if (!defined HRT_CSIM && !defined HRT_RTL)
		IA_CSS_ERROR("CSS code version (%s) and firmware version (%s) mismatch!",
				file_header->version, release_version);
		return IA_CSS_ERR_VERSION_MISMATCH;
#endif
	} else {
		IA_CSS_LOG("successfully load firmware version %s", release_version);
	}

	/* some sanity checks */
	if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h))
		return IA_CSS_ERR_INTERNAL_ERROR;

	if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h))
		return IA_CSS_ERR_INTERNAL_ERROR;

	sh_css_num_binaries = file_header->binary_nr;
	/* Only allocate memory for ISP blob info */
	if (sh_css_num_binaries > NUM_OF_SPS) {
		sh_css_blob_info = sh_css_malloc(
					(sh_css_num_binaries - NUM_OF_SPS) *
					sizeof(*sh_css_blob_info));
		if (sh_css_blob_info == NULL)
			return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
	} else {
		sh_css_blob_info = NULL;
	}

	fw_minibuffer = sh_css_malloc(sh_css_num_binaries * sizeof(struct fw_param));
	if (fw_minibuffer == NULL)
		return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
	memset(fw_minibuffer, 0, sh_css_num_binaries * sizeof(struct fw_param));

	for (i = 0; i < sh_css_num_binaries; i++) {
		struct ia_css_fw_info *bi = &binaries[i];
		/* note: the var below is made static as it is quite large;
		   if it is not static it ends up on the stack which could
		   cause issues for drivers
		*/
		static struct ia_css_blob_descr bd;
		enum ia_css_err err;

		err = sh_css_load_blob_info(fw_data, bi, &bd, i);

		if (err != IA_CSS_SUCCESS)
			return IA_CSS_ERR_INTERNAL_ERROR;

		if (bi->blob.offset + bi->blob.size > fw_size)
			return IA_CSS_ERR_INTERNAL_ERROR;

		if (bi->type == ia_css_sp_firmware) {
			if (i != SP_FIRMWARE)
				return IA_CSS_ERR_INTERNAL_ERROR;
			err = setup_sp(bi, fw_data, &sh_css_sp_fw, i);
			if (err != IA_CSS_SUCCESS)
				return err;
#if defined(HAS_SEC_SP)
		} else if (bi->type == ia_css_sp1_firmware) {
			if (i != SP1_FIRMWARE)
				return IA_CSS_ERR_INTERNAL_ERROR;
			err = setup_sp(bi, fw_data, &sh_css_sp1_fw, i);
			if (err != IA_CSS_SUCCESS)
				return err;
#endif /* HAS_SEC_SP */
		} else {
			/* All subsequent binaries (i>NUM_OF_SPS) are ISP firmware */
			if (i < NUM_OF_SPS)
				return IA_CSS_ERR_INTERNAL_ERROR;
			if (bi->type != ia_css_isp_firmware)
				return IA_CSS_ERR_INTERNAL_ERROR;
			if (sh_css_blob_info == NULL) /* cannot happen but KW does not see this */
				return IA_CSS_ERR_INTERNAL_ERROR;
			sh_css_blob_info[i-NUM_OF_SPS] = bd;
		}
	}

	return IA_CSS_SUCCESS;
}