提交 f4e526ff 编写于 作者: B Bjorn Andersson

soc: qcom: mdt_loader: Extract PAS operations

Rather than passing a boolean to indicate if the PAS operations should
be performed from within __mdt_load(), extract them to their own helper
function.

This will allow clients to invoke this directly, with some
qcom_scm_pas_metadata context that they later needs to release, without
further having to complicate the prototype of qcom_mdt_load().
Signed-off-by: NBjorn Andersson <bjorn.andersson@linaro.org>
Reviewed-by: NDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20220128025513.97188-9-bjorn.andersson@linaro.org
上级 ebeb20a9
...@@ -188,28 +188,31 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len, ...@@ -188,28 +188,31 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
} }
EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata); EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata);
static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, /**
const char *fw_name, int pas_id, void *mem_region, * qcom_mdt_pas_init() - initialize PAS region for firmware loading
phys_addr_t mem_phys, size_t mem_size, * @dev: device handle to associate resources with
phys_addr_t *reloc_base, bool pas_init) * @fw: firmware object for the mdt file
* @firmware: name of the firmware, for construction of segment file names
* @pas_id: PAS identifier
* @mem_phys: physical address of allocated memory region
* @ctx: PAS metadata context, to be released by caller
*
* Returns 0 on success, negative errno otherwise.
*/
int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, phys_addr_t mem_phys,
struct qcom_scm_pas_metadata *ctx)
{ {
const struct elf32_phdr *phdrs; const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr; const struct elf32_phdr *phdr;
const struct elf32_hdr *ehdr; const struct elf32_hdr *ehdr;
phys_addr_t mem_reloc;
phys_addr_t min_addr = PHYS_ADDR_MAX; phys_addr_t min_addr = PHYS_ADDR_MAX;
phys_addr_t max_addr = 0; phys_addr_t max_addr = 0;
size_t metadata_len; size_t metadata_len;
ssize_t offset;
void *metadata; void *metadata;
bool relocate = false; int ret;
void *ptr;
int ret = 0;
int i; int i;
if (!fw || !mem_region || !mem_phys || !mem_size)
return -EINVAL;
ehdr = (struct elf32_hdr *)fw->data; ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1); phdrs = (struct elf32_phdr *)(ehdr + 1);
...@@ -219,9 +222,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, ...@@ -219,9 +222,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (!mdt_phdr_valid(phdr)) if (!mdt_phdr_valid(phdr))
continue; continue;
if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
relocate = true;
if (phdr->p_paddr < min_addr) if (phdr->p_paddr < min_addr)
min_addr = phdr->p_paddr; min_addr = phdr->p_paddr;
...@@ -229,32 +229,66 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, ...@@ -229,32 +229,66 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K); max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K);
} }
if (pas_init) {
metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev); metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev);
if (IS_ERR(metadata)) { if (IS_ERR(metadata)) {
ret = PTR_ERR(metadata); ret = PTR_ERR(metadata);
dev_err(dev, "error %d reading firmware %s metadata\n", dev_err(dev, "error %d reading firmware %s metadata\n", ret, fw_name);
ret, fw_name);
goto out; goto out;
} }
ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, NULL); ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, ctx);
kfree(metadata); kfree(metadata);
if (ret) { if (ret) {
/* Invalid firmware metadata */ /* Invalid firmware metadata */
dev_err(dev, "error %d initializing firmware %s\n", dev_err(dev, "error %d initializing firmware %s\n", ret, fw_name);
ret, fw_name);
goto out; goto out;
} }
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
if (ret) { if (ret) {
/* Unable to set up relocation */ /* Unable to set up relocation */
dev_err(dev, "error %d setting up firmware %s\n", dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name);
ret, fw_name);
goto out; goto out;
} }
out:
return ret;
}
EXPORT_SYMBOL_GPL(qcom_mdt_pas_init);
static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, void *mem_region,
phys_addr_t mem_phys, size_t mem_size,
phys_addr_t *reloc_base, bool pas_init)
{
const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr;
const struct elf32_hdr *ehdr;
phys_addr_t mem_reloc;
phys_addr_t min_addr = PHYS_ADDR_MAX;
ssize_t offset;
bool relocate = false;
void *ptr;
int ret = 0;
int i;
if (!fw || !mem_region || !mem_phys || !mem_size)
return -EINVAL;
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];
if (!mdt_phdr_valid(phdr))
continue;
if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
relocate = true;
if (phdr->p_paddr < min_addr)
min_addr = phdr->p_paddr;
} }
if (relocate) { if (relocate) {
...@@ -319,8 +353,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, ...@@ -319,8 +353,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (reloc_base) if (reloc_base)
*reloc_base = mem_reloc; *reloc_base = mem_reloc;
out:
return ret; return ret;
} }
...@@ -342,6 +374,12 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw, ...@@ -342,6 +374,12 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw,
phys_addr_t mem_phys, size_t mem_size, phys_addr_t mem_phys, size_t mem_size,
phys_addr_t *reloc_base) phys_addr_t *reloc_base)
{ {
int ret;
ret = qcom_mdt_pas_init(dev, fw, firmware, pas_id, mem_phys, NULL);
if (ret)
return ret;
return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys, return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
mem_size, reloc_base, true); mem_size, reloc_base, true);
} }
......
...@@ -10,10 +10,14 @@ ...@@ -10,10 +10,14 @@
struct device; struct device;
struct firmware; struct firmware;
struct qcom_scm_pas_metadata;
#if IS_ENABLED(CONFIG_QCOM_MDT_LOADER) #if IS_ENABLED(CONFIG_QCOM_MDT_LOADER)
ssize_t qcom_mdt_get_size(const struct firmware *fw); ssize_t qcom_mdt_get_size(const struct firmware *fw);
int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, phys_addr_t mem_phys,
struct qcom_scm_pas_metadata *pas_metadata_ctx);
int qcom_mdt_load(struct device *dev, const struct firmware *fw, int qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, void *mem_region, const char *fw_name, int pas_id, void *mem_region,
phys_addr_t mem_phys, size_t mem_size, phys_addr_t mem_phys, size_t mem_size,
...@@ -33,6 +37,13 @@ static inline ssize_t qcom_mdt_get_size(const struct firmware *fw) ...@@ -33,6 +37,13 @@ static inline ssize_t qcom_mdt_get_size(const struct firmware *fw)
return -ENODEV; return -ENODEV;
} }
static inline int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, phys_addr_t mem_phys,
struct qcom_scm_pas_metadata *pas_metadata_ctx)
{
return -ENODEV;
}
static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw, static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, const char *fw_name, int pas_id,
void *mem_region, phys_addr_t mem_phys, void *mem_region, phys_addr_t mem_phys,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册