On Fri, Apr 22, 2016 at 07:38:21PM +0530, Vinod Koul wrote: > From: Shreyas NC <shreyas.nc@xxxxxxxxx> > > Module params like module_id and loadable flag can be changed > in the DSP Firmware. These are kept in the firmware manifest > and driver should read these values from this manifest. > > So, add support to parse the DSP firmware manifest and > read these module params. > > Signed-off-by: Shreyas NC <shreyas.nc@xxxxxxxxx> > Signed-off-by: Vinod Koul <vinod.koul@xxxxxxxxx> Hey Mark, Is this patch still in your review queue or you need us to address something here > --- > Changes in v3: > add bound check for firmware file > > sound/soc/intel/skylake/Makefile | 2 +- > sound/soc/intel/skylake/skl-dsp-parse.c | 118 ++++++++++++++++++++++++++++++++ > sound/soc/intel/skylake/skl-dsp-parse.h | 107 +++++++++++++++++++++++++++++ > sound/soc/intel/skylake/skl-sst-ipc.h | 4 ++ > sound/soc/intel/skylake/skl-sst.c | 11 ++- > sound/soc/intel/skylake/skl-topology.c | 5 ++ > 6 files changed, 245 insertions(+), 2 deletions(-) > create mode 100644 sound/soc/intel/skylake/skl-dsp-parse.c > create mode 100644 sound/soc/intel/skylake/skl-dsp-parse.h > > diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile > index c28f5d0e1d99..e2fb5b763b21 100644 > --- a/sound/soc/intel/skylake/Makefile > +++ b/sound/soc/intel/skylake/Makefile > @@ -5,6 +5,6 @@ obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o > > # Skylake IPC Support > snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \ > - skl-sst.o bxt-sst.o > + skl-sst.o skl-dsp-parse.o bxt-sst.o > > obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o > diff --git a/sound/soc/intel/skylake/skl-dsp-parse.c b/sound/soc/intel/skylake/skl-dsp-parse.c > new file mode 100644 > index 000000000000..a3cd5d7ab246 > --- /dev/null > +++ b/sound/soc/intel/skylake/skl-dsp-parse.c > @@ -0,0 +1,118 @@ > +/* > + * skl-dsp-parse.c - Implements DSP firmware parsing > + * > + * Copyright (C) 2016 Intel Corp > + * Author: Shreyas NC <shreyas.nc@xxxxxxxxx> > + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as version 2, as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * General Public License for more details. > + */ > + > +#include <linux/module.h> > +#include <linux/types.h> > +#include <linux/kernel.h> > +#include <linux/device.h> > +#include "../common/sst-dsp.h" > +#include "../common/sst-dsp-priv.h" > +#include "skl-tplg-interface.h" > +#include "skl-sst-ipc.h" > +#include "skl-dsp-parse.h" > + > +/* > + * Get the module id for the module by checking > + * the table for the UUID for the module > + */ > +int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid, > + struct skl_dfw_module *dfw_config) > +{ > + int i, num; > + struct uuid_tbl *tbl; > + uuid_le *uuid_mod; > + > + tbl = ctx->tbl; > + num = ctx->num_modules; > + uuid_mod = (uuid_le *)uuid; > + > + for (i = 0; i < num; i++) { > + if (uuid_le_cmp(*uuid_mod, tbl[i].uuid) == 0) { > + dfw_config->module_id = tbl[i].module_id; > + dfw_config->is_loadable = tbl[i].is_loadable; > + return 0; > + } > + } > + return -EINVAL; > +} > +EXPORT_SYMBOL_GPL(snd_skl_get_module_info); > + > +/* > + * Parse the firmware binary to get the UUID, module id > + * and loadable flags > + */ > +int snd_skl_parse_fw_bin(struct sst_dsp *ctx) > +{ > + struct adsp_fw_hdr *adsp_hdr; > + struct adsp_module_entry *mod_entry; > + int i, num_entry; > + uuid_le *uuid_bin; > + const char *buf; > + struct skl_sst *skl = ctx->thread_context; > + struct uuid_tbl *tbl; > + > + /* Get the FW pointer to derive ADSP header */ > + buf = ctx->fw->data; > + > + adsp_hdr = (struct adsp_fw_hdr *)(buf + SKL_ADSP_FW_BIN_HDR_OFFSET); > + > + mod_entry = (struct adsp_module_entry *) > + (buf + SKL_ADSP_FW_BIN_HDR_OFFSET + adsp_hdr->header_len); > + > + num_entry = adsp_hdr->num_module_entries; > + > + tbl = devm_kzalloc(ctx->dev, > + num_entry * sizeof(struct uuid_tbl), GFP_KERNEL); > + > + if (!tbl) > + return -ENOMEM; > + > + /* > + * Read the UUID(GUID) from FW Manifest. > + * The 16 byte UUID is of the format: > + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX > + * Populate the UUID table to store module_id > + * and loadable flags for the module. > + */ > + > + for (i = 0; i < num_entry; i++, mod_entry++) { > + > + /* > + * we check if current pointer is larger than file size from > + * base value to check excceding the file while parsing > + */ > + if ((const char *)mod_entry >= buf + ctx->fw->size) { > + dev_err(ctx->dev, > + "Exceeds file bound: Entry %d Ptr %p\n", > + i, mod_entry); > + > + return -EIO; > + } > + > + uuid_bin = (uuid_le *)mod_entry->uuid.id; > + memcpy(&tbl[i].uuid, uuid_bin, sizeof(tbl[i].uuid)); > + > + tbl[i].module_id = i; > + tbl[i].is_loadable = mod_entry->type.load_type; > + } > + > + skl->tbl = tbl; > + skl->num_modules = num_entry; > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(snd_skl_parse_fw_bin); > diff --git a/sound/soc/intel/skylake/skl-dsp-parse.h b/sound/soc/intel/skylake/skl-dsp-parse.h > new file mode 100644 > index 000000000000..cfdb24c45035 > --- /dev/null > +++ b/sound/soc/intel/skylake/skl-dsp-parse.h > @@ -0,0 +1,107 @@ > +/* > + * skl-dsp-parse.h > + * > + * Copyright (C) 2016 Intel Corp > + * Author: Shreyas NC <shreyas.nc@xxxxxxxxx> > + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as version 2, as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * General Public License for more details. > + */ > + > +#include <asm/types.h> > +#include <linux/types.h> > +#include <linux/uuid.h> > +#include "skl-tplg-interface.h" > +#include "../common/sst-dsp-priv.h" > + > +#define SKL_ADSP_FW_BIN_HDR_OFFSET 0x284 > +#define UUID_STR_SIZE 37 > +#define DEFAULT_HASH_SHA256_LEN 32 > + > +struct skl_dfw_module_mod { > + char name[100]; > + struct skl_dfw_module skl_dfw_mod; > +}; > + > +struct UUID { > + u8 id[16]; > +}; > + > +union seg_flags { > + u32 ul; > + struct { > + u32 contents : 1; > + u32 alloc : 1; > + u32 load : 1; > + u32 read_only : 1; > + u32 code : 1; > + u32 data : 1; > + u32 _rsvd0 : 2; > + u32 type : 4; > + u32 _rsvd1 : 4; > + u32 length : 16; > + } r; > +} __packed; > + > +struct segment_desc { > + union seg_flags flags; > + u32 v_base_addr; > + u32 file_offset; > +}; > + > +struct module_type { > + u32 load_type : 4; > + u32 auto_start : 1; > + u32 domain_ll : 1; > + u32 domain_dp : 1; > + u32 rsvd_ : 25; > +} __packed; > + > +struct adsp_module_entry { > + u32 struct_id; > + u8 name[8]; > + struct UUID uuid; > + struct module_type type; > + u8 hash1[DEFAULT_HASH_SHA256_LEN]; > + u32 entry_point; > + u16 cfg_offset; > + u16 cfg_count; > + u32 affinity_mask; > + u16 instance_max_count; > + u16 instance_bss_size; > + struct segment_desc segments[3]; > +} __packed; > + > +struct adsp_fw_hdr { > + u32 header_id; > + u32 header_len; > + u8 name[8]; > + u32 preload_page_count; > + u32 fw_image_flags; > + u32 feature_mask; > + u16 major_version; > + u16 minor_version; > + u16 hotfix_version; > + u16 build_version; > + u32 num_module_entries; > + u32 hw_buf_base_addr; > + u32 hw_buf_length; > + u32 load_offset; > +} __packed; > + > +struct uuid_tbl { > + uuid_le uuid; > + int module_id; > + int is_loadable; > +}; > + > +int snd_skl_parse_fw_bin(struct sst_dsp *ctx); > +int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid, > + struct skl_dfw_module *dfw_config); > diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h > index d59d1ba62a43..67d56be8cb77 100644 > --- a/sound/soc/intel/skylake/skl-sst-ipc.h > +++ b/sound/soc/intel/skylake/skl-sst-ipc.h > @@ -60,6 +60,10 @@ struct skl_sst { > void (*enable_miscbdcge)(struct device *dev, bool enable); > /*Is CGCTL.MISCBDCGE disabled*/ > bool miscbdcg_disabled; > + > + /* Populate module information */ > + struct uuid_tbl *tbl; > + int num_modules; > }; > > struct skl_ipc_init_instance_msg { > diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c > index bec4a7c486fd..df7964fd09c3 100644 > --- a/sound/soc/intel/skylake/skl-sst.c > +++ b/sound/soc/intel/skylake/skl-sst.c > @@ -25,6 +25,7 @@ > #include "../common/sst-dsp-priv.h" > #include "../common/sst-ipc.h" > #include "skl-sst-ipc.h" > +#include "skl-dsp-parse.h" > > #define SKL_BASEFW_TIMEOUT 300 > #define SKL_INIT_TIMEOUT 1000 > @@ -70,7 +71,7 @@ static int skl_transfer_firmware(struct sst_dsp *ctx, > > static int skl_load_base_firmware(struct sst_dsp *ctx) > { > - int ret = 0, i; > + int ret = 0, i, err; > struct skl_sst *skl = ctx->thread_context; > u32 reg; > > @@ -84,6 +85,14 @@ static int skl_load_base_firmware(struct sst_dsp *ctx) > skl_dsp_disable_core(ctx); > return -EIO; > } > + > + err = snd_skl_parse_fw_bin(ctx); > + if (err < 0) { > + dev_err(ctx->dev, > + "Firmware parsing err: %d\n", ret); > + release_firmware(ctx->fw); > + return err; > + } > } > > ret = skl_dsp_boot(ctx); > diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c > index a1f4478fabcb..f690b016203c 100644 > --- a/sound/soc/intel/skylake/skl-topology.c > +++ b/sound/soc/intel/skylake/skl-topology.c > @@ -28,6 +28,7 @@ > #include "skl-tplg-interface.h" > #include "../common/sst-dsp.h" > #include "../common/sst-dsp-priv.h" > +#include "skl-dsp-parse.h" > > #define SKL_CH_FIXUP_MASK (1 << 0) > #define SKL_RATE_FIXUP_MASK (1 << 1) > @@ -1566,6 +1567,10 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, > w->priv = mconfig; > memcpy(&mconfig->guid, &dfw_config->uuid, 16); > > + ret = snd_skl_get_module_info(skl->skl_sst, mconfig->guid, dfw_config); > + if (ret < 0) > + return ret; > + > mconfig->id.module_id = dfw_config->module_id; > mconfig->id.instance_id = dfw_config->instance_id; > mconfig->mcps = dfw_config->max_mcps; > -- > 1.9.1 > -- ~Vinod _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel