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; }