- void *ptr;
- int ret = 0;
-
- ptr = ioremap_nocache(paddr, phdr->p_memsz);
- if (!ptr) {
- dev_err(rproc->dev, "failed to ioremap segment area (%pa+0x%x)\n", &paddr, phdr->p_memsz);
- return -EBUSY;
- }
-
- if (phdr->p_filesz) {
- ret = request_firmware(&fw, fw_name, rproc->dev);
- if (ret) {
- dev_err(rproc->dev, "failed to load %s\n", fw_name);
- goto out;
- }
-
- memcpy_toio(ptr, fw->data, fw->size);
-
- release_firmware(fw);
- }
-
- if (phdr->p_memsz > phdr->p_filesz)
- memset_io(ptr + phdr->p_filesz, 0,
- phdr->p_memsz - phdr->p_filesz);
-
- printk("DEBUG:pil: verifing %s size: %x\n",fw_name, phdr->p_memsz);
- qproc_verify_segment(rproc, paddr, phdr->p_memsz);
-
-out:
- iounmap(ptr);
- return ret;
-}
-
-static int
-qproc_load_segments(struct qproc *qproc, const struct firmware *fw)
-{
- struct device *dev = qproc->dev;
- struct elf32_hdr *ehdr;
- struct elf32_phdr *phdr;
- int i, ret = 0;
- const u8 *elf_data = fw->data;
- const struct firmware *seg_fw;
- char fw_name[20];
-
- const struct mdt_hdr *mdt;
- phys_addr_t min_addr = (phys_addr_t)ULLONG_MAX;
- phys_addr_t max_addr = 0;
- size_t align = 0;
- bool relocatable = false;
- phys_addr_t paddr;
-
-
- ehdr = (struct elf32_hdr *)elf_data;
- phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
-
-
- mdt = (struct mdt_hdr *)fw->data;
- ehdr = &mdt->hdr;
-
- for (i = 0; i < ehdr->e_phnum; i++) {
- phdr = &mdt->phdr[i];
-
- if (!segment_is_loadable(phdr))
- continue;
-
- if (phdr->p_paddr < min_addr) {
- min_addr = phdr->p_paddr;
-
- if (segment_is_relocatable(phdr)) {
- align = phdr->p_align;
- relocatable = true;
- }
- }
-
- if (phdr->p_paddr + phdr->p_memsz > max_addr)
- max_addr = round_up(phdr->p_paddr + phdr->p_memsz, SZ_4K);
- }
-
- ehdr = (struct elf32_hdr *)elf_data;
- phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
- /* go through the available ELF segments */
- for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
- u32 da = phdr->p_paddr;
- u32 paddr = phdr->p_paddr;
- u32 memsz = phdr->p_memsz;
- u32 filesz = phdr->p_filesz;
- void *ptr;
-
- if (!segment_is_loadable(phdr))
- continue;
- /*
- if (phdr->p_type != PT_LOAD)
- continue;
-
- if (segment_is_hash(phdr->p_flags))
- continue;
-
- if (filesz == 0)
- continue;
-*/
- //dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
- pr_emerg("phdr(%d): type %d paddr 0x%x memsz 0x%x filesz 0x%x\n",
- i, phdr->p_type, paddr, memsz, filesz);
-
- if (filesz > memsz) {
- dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
- filesz, memsz);
- ret = -EINVAL;
- break;
- }
-
- paddr = relocatable ?
- (phdr->p_paddr - min_addr + qproc->reloc_phys) :
- phdr->p_paddr;
-
- pr_emerg("Relocated-phdr(%d): type %d paddr 0x%x memsz 0x%x filesz 0x%x\n",
- i, phdr->p_type, paddr, memsz, filesz);
-// if (filesz) {
- snprintf(fw_name, sizeof(fw_name), "modem.b%02d", i);
- ret = qproc_load_segment(qproc, fw_name, phdr, paddr);
-// }
-#if 0
-
- ptr = ioremap(da, memsz);
- if (!ptr) {
- dev_err(qproc->dev, "failed to allocate mba metadata buffer\n");
- ret = -ENOMEM;
- break;
- }
-
- if (filesz) {
- snprintf(fw_name, sizeof(fw_name), "modem.b%02d", i);
- ret = request_firmware(&seg_fw, fw_name, qproc->dev);
- if (ret) {
- iounmap(ptr);
- break;
- }
-
- memcpy(ptr, seg_fw->data, filesz);
-
- release_firmware(seg_fw);
- }
-
- if (memsz > filesz)
- memset(ptr + filesz, 0, memsz - filesz);
-
-
-
- wmb();
- iounmap(ptr);
-#endif
- }
-
- return ret;
-}
-
-static int qproc_verify_segments(struct qproc *qproc, const struct firmware *fw)
-{
- struct elf32_hdr *ehdr;
- struct elf32_phdr *phdr;
- const u8 *elf_data = fw->data;
- unsigned long timeout;
- phys_addr_t min_addr = (phys_addr_t)ULLONG_MAX;
- u32 size = 0;
- s32 val;
- int ret;
- int i;
- u32 v;
-
- ehdr = (struct elf32_hdr *)elf_data;
- phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
-
- v = readl_relaxed(qproc->rmb_base + RMB_PMI_CODE_LENGTH);
- dev_err(qproc->dev, "RMB_PMI_CODE_LENGTH: %pa\n", &v);
-
- msleep(1);
-
-
-#if 1
- for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
- phys_addr_t da = phdr->p_paddr;
- u32 memsz = phdr->p_memsz;
-
-
- if (!segment_is_loadable(phdr))
- continue;
- /*
- if (phdr->p_type != PT_LOAD)
- continue;
-*/
- dev_err(qproc->dev, "0x%x %d %d\n", phdr->p_paddr, segment_is_hash(phdr->p_flags), !!(phdr->p_flags & BIT(27)));
-
- /*
- if (segment_is_hash(phdr->p_flags))
- continue;
-
- if (memsz == 0)
- continue;
- */
- if (da < min_addr)
- min_addr = da;
-
- size += memsz;
- }
-
- dev_err(qproc->dev, "verify: %pa:%pa\n", &min_addr, &size);
- v = readl_relaxed(qproc->rmb_base + RMB_PMI_CODE_LENGTH);
- dev_err(qproc->dev, "RMB_PMI_CODE_LENGTH: %pa\n", &v);
-#if 0
-if (v == 0) {
- writel_relaxed(min_addr, qproc->rmb_base + RMB_PMI_CODE_START);
- writel(CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND);
-}
- writel(size, qproc->rmb_base + RMB_PMI_CODE_LENGTH);
-#endif
-#endif
-
- v = readl_relaxed(qproc->rmb_base + RMB_PMI_CODE_LENGTH);
- dev_err(qproc->dev, "RMB_PMI_CODE_LENGTH: %pa\n", &v);
-
- printk("DEBUG:pil: status... %08x\n", readl_relaxed(qproc->rmb_base + RMB_MBA_STATUS));
-
- timeout = jiffies + 10 * HZ;
- for (;;) {
- msleep(1);
-
- val = readl(qproc->rmb_base + RMB_MBA_STATUS);
- if (val == STATUS_AUTH_COMPLETE || val < 0)
- break;
-
- if (time_after(jiffies, timeout))
- break;
- }
- if (val == 0) {
- dev_err(qproc->dev, "MBA authentication of headers timed out\n");
- ret = -ETIMEDOUT;
- goto out;
- } else if (val < 0) {
- dev_err(qproc->dev, "MBA returned error %d for segments\n", val);
- ret = -EINVAL;
- goto out;
- }
-
- ret = 0;
-out:
- return ret;
-
-
-}
-
-static int qproc_msa_mba_auth(struct qproc *qproc)
-{
- unsigned long timeout;
- s32 val;