// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // // Copyright(c) 2022 Intel Corporation
/* * At the start of the firmware image we must have an extended manifest. * Verify that the magic number is correct.
*/ if (ext_man_hdr->id != SOF_EXT_MAN4_MAGIC_NUMBER) {
dev_err(sdev->dev, "Unexpected extended manifest magic number: %#x\n",
ext_man_hdr->id); return -EINVAL;
}
fw_hdr_offset = ipc4_data->manifest_fw_hdr_offset; if (!fw_hdr_offset) return -EINVAL;
if (remaining <= ext_man_hdr->len + fw_hdr_offset + sizeof(*fw_header)) {
dev_err(sdev->dev, "Invalid firmware size %zu, should be at least %zu\n",
remaining, ext_man_hdr->len + fw_hdr_offset + sizeof(*fw_header)); return -EINVAL;
}
/* copy the fw_version of basefw into debugfs at first boot */ if (fw == sdev->basefw.fw) {
sdev->fw_version.major = fw_header->major_version;
sdev->fw_version.minor = fw_header->minor_version;
sdev->fw_version.micro = fw_header->hotfix_version;
sdev->fw_version.build = fw_header->build_version;
}
fw_lib->modules = devm_kmalloc_array(sdev->dev, fw_header->num_module_entries, sizeof(*fw_module), GFP_KERNEL); if (!fw_lib->modules) return -ENOMEM;
/* Fix up the module ID numbers within the library */ for (i = 0; i < fw_lib->num_modules; i++)
fw_lib->modules[i].man4_module_entry.id |= (lib_id << SOF_IPC4_MOD_LIB_ID_SHIFT);
/* * Make sure that the DSP is booted and stays up while attempting the * loading the library for the first time
*/
ret = pm_runtime_resume_and_get(sdev->dev); if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(sdev->dev, "%s: pm_runtime resume failed: %d\n",
__func__, ret); goto release;
}
ret = ipc4_data->load_library(sdev, fw_lib, false);
/** * sof_ipc4_complete_split_release - loads the library parts of a split firmware * @sdev: SOF device * * With IPC4 the firmware can be a single binary or a split release. * - single binary: only the basefw * - split release: basefw and two libraries (openmodules, debug) * * With split firmware release it is also allowed that for example only the * debug library is present (the openmodules content is built in the basefw). * * To handle the permutations try to load the openmodules then the debug * libraries as optional ones after the basefw boot. * * The libraries for the split release are stored alongside the basefw on the * filesystem.
*/ int sof_ipc4_complete_split_release(struct snd_sof_dev *sdev)
{ staticconstchar * const lib_bundle[] = { "openmodules", "debug" }; constchar *fw_filename = sdev->pdata->fw_filename; constchar *lib_filename, *p;
size_t lib_name_base_size; unsignedlong lib_id = 1; char *lib_name_base; int i;
p = strstr(fw_filename, ".ri"); if (!p || strlen(p) != 3) {
dev_info(sdev->dev, "%s: Firmware name '%s' is missing .ri extension\n",
__func__, fw_filename); return 0;
}
/* Space for the firmware basename + '\0', without the extension */
lib_name_base_size = strlen(fw_filename) - 2;
lib_name_base = kzalloc(lib_name_base_size, GFP_KERNEL); if (!lib_name_base) return -ENOMEM;
/* * strscpy will 0 terminate the copied string, removing the '.ri' from * the end of the fw_filename, for example: * fw_filename: "sof-ptl.ri\0" * lib_name_base: "sof-ptl\0"
*/
strscpy(lib_name_base, fw_filename, lib_name_base_size);
for (i = 0; i < ARRAY_SIZE(lib_bundle); i++) { int ret;
xa_for_each(&ipc4_data->fw_lib_xa, lib_id, fw_lib) { for (i = 0; i < fw_lib->num_modules; i++) { if (guid_equal(uuid, &fw_lib->modules[i].man4_module_entry.uuid)) return &fw_lib->modules[i];
}
}
/* * Do not attempt to load external library in case the maximum number of * firmware libraries have been already loaded
*/ if ((lib_id + 1) == ipc4_data->max_libs_count) {
dev_err(sdev->dev, "%s: Maximum allowed number of libraries reached (%u)\n",
__func__, ipc4_data->max_libs_count); return NULL;
}
/* The module cannot be found, try to load it as a library */
ret = sof_ipc4_load_library_by_uuid(sdev, lib_id + 1, uuid); if (ret) return NULL;
/* Look for the module in the newly loaded library, it should be available now */
xa_for_each_start(&ipc4_data->fw_lib_xa, lib_id, fw_lib, lib_id) { for (i = 0; i < fw_lib->num_modules; i++) { if (guid_equal(uuid, &fw_lib->modules[i].man4_module_entry.uuid)) return &fw_lib->modules[i];
}
}
int sof_ipc4_reload_fw_libraries(struct snd_sof_dev *sdev)
{ struct sof_ipc4_fw_data *ipc4_data = sdev->private; struct sof_ipc4_fw_library *fw_lib; unsignedlong lib_id; int ret = 0;
xa_for_each_start(&ipc4_data->fw_lib_xa, lib_id, fw_lib, 1) {
ret = ipc4_data->load_library(sdev, fw_lib, true); if (ret) {
dev_err(sdev->dev, "%s: Failed to reload library: %s, %d\n",
__func__, fw_lib->name, ret); break;
}
}
return ret;
}
/** * sof_ipc4_update_cpc_from_manifest - Update the cpc in base config from manifest * @sdev: SOF device * @fw_module: pointer struct sof_ipc4_fw_module to parse * @basecfg: Pointer to the base_config to update
*/ void sof_ipc4_update_cpc_from_manifest(struct snd_sof_dev *sdev, struct sof_ipc4_fw_module *fw_module, struct sof_ipc4_base_module_cfg *basecfg)
{ conststruct sof_man4_module_config *fw_mod_cfg;
u32 cpc_pick = 0;
u32 max_cpc = 0; constchar *msg; int i;
if (!fw_module->fw_mod_cfg) {
msg = "No mod_cfg available for CPC lookup in the firmware file's manifest"; goto no_cpc;
}
/* * Find the best matching (highest) CPC value based on the module's * IBS/OBS configuration inferred from the audio format selection. * * The CPC value in each module config entry has been measured and * recorded as a IBS/OBS/CPC triplet and stored in the firmware file's * manifest
*/
fw_mod_cfg = fw_module->fw_mod_cfg; for (i = 0; i < fw_module->man4_module_entry.cfg_count; i++) { if (basecfg->obs == fw_mod_cfg[i].obs &&
basecfg->ibs == fw_mod_cfg[i].ibs &&
cpc_pick < fw_mod_cfg[i].cpc)
cpc_pick = fw_mod_cfg[i].cpc;
if (max_cpc < fw_mod_cfg[i].cpc)
max_cpc = fw_mod_cfg[i].cpc;
}
basecfg->cpc = cpc_pick;
/* We have a matching configuration for CPC */ if (basecfg->cpc) return;
/* * No matching IBS/OBS found, the firmware manifest is missing * information in the module's module configuration table.
*/ if (!max_cpc)
msg = "No CPC value available in the firmware file's manifest"; elseif (!cpc_pick)
msg = "No CPC match in the firmware file's manifest";
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.