staticconstchar * const fwio_errors[] = {
[ERR_INVALID_SEC_TYPE] = "Invalid section type or wrong encryption",
[ERR_SIG_VERIF_FAILED] = "Signature verification failed",
[ERR_AES_CTRL_KEY] = "AES control key not initialized",
[ERR_ECC_PUB_KEY] = "ECC public key not initialized",
[ERR_MAC_KEY] = "MAC key not initialized",
};
/* request_firmware() allocate data using vmalloc(). It is not compatible with underlying hardware * that use DMA. Function below detect this case and allocate a bounce buffer if necessary. * * Notice that, in doubt, you can enable CONFIG_DEBUG_SG to ask kernel to detect this problem at * runtime (else, kernel silently fail). * * NOTE: it may also be possible to use 'pages' from struct firmware and avoid bounce buffer
*/ staticint wfx_sram_write_dma_safe(struct wfx_dev *wdev, u32 addr, const u8 *buf, size_t len)
{ int ret; const u8 *tmp;
if (!virt_addr_valid(buf)) {
tmp = kmemdup(buf, len, GFP_KERNEL); if (!tmp) return -ENOMEM;
} else {
tmp = buf;
}
ret = wfx_sram_buf_write(wdev, addr, tmp, len); if (tmp != buf)
kfree(tmp); return ret;
}
staticint get_firmware(struct wfx_dev *wdev, u32 keyset_chip, conststruct firmware **fw, int *file_offset)
{ int keyset_file; char filename[256]; constchar *data; int ret;
snprintf(filename, sizeof(filename), "%s_%02X.sec",
wdev->pdata.file_fw, keyset_chip);
ret = firmware_request_nowarn(fw, filename, wdev->dev); if (ret) {
dev_info(wdev->dev, "can't load %s, falling back to %s.sec\n",
filename, wdev->pdata.file_fw);
snprintf(filename, sizeof(filename), "%s.sec", wdev->pdata.file_fw);
ret = request_firmware(fw, filename, wdev->dev); if (ret) {
dev_err(wdev->dev, "can't load %s\n", filename);
*fw = NULL; return ret;
}
}
if (len % DNLD_BLOCK_SIZE) {
dev_err(wdev->dev, "firmware size is not aligned. Buffer overrun will occur\n"); return -EIO;
}
offs = 0; while (offs < len) {
start = ktime_get(); for (;;) {
now = ktime_get(); if (offs + DNLD_BLOCK_SIZE - bytes_done < DNLD_FIFO_SIZE) break; if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT))) return -ETIMEDOUT;
ret = wfx_sram_reg_read(wdev, WFX_DCA_GET, &bytes_done); if (ret < 0) return ret;
} if (ktime_compare(now, start))
dev_dbg(wdev->dev, "answer after %lldus\n", ktime_us_delta(now, start));
ret = wfx_sram_write_dma_safe(wdev, WFX_DNLD_FIFO + (offs % DNLD_FIFO_SIZE),
data + offs, DNLD_BLOCK_SIZE); if (ret < 0) return ret;
/* The device seems to not support writing 0 in this register during first loop */
offs += DNLD_BLOCK_SIZE;
ret = wfx_sram_reg_write(wdev, WFX_DCA_PUT, offs); if (ret < 0) return ret;
} return 0;
}
start = ktime_get();
ret = upload_firmware(wdev, fw->data + header_size, fw->size - header_size); if (ret) goto error;
dev_dbg(wdev->dev, "firmware load after %lldus\n",
ktime_us_delta(ktime_get(), start));
wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_COMPLETE);
ret = wait_ncp_status(wdev, NCP_AUTH_OK); /* Legacy ROM support */ if (ret < 0)
ret = wait_ncp_status(wdev, NCP_PUB_KEY_RDY); if (ret < 0) goto error;
wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_OK_TO_JUMP);
error:
kfree(buf);
release_firmware(fw); if (ret)
print_boot_status(wdev); return ret;
}
ret = wfx_control_reg_write(wdev, CTRL_WLAN_WAKEUP); if (ret < 0) return -EIO;
start = ktime_get(); for (;;) {
ret = wfx_control_reg_read(wdev, ®);
now = ktime_get(); if (reg & CTRL_WLAN_READY) break; if (ktime_after(now, ktime_add_ms(start, wakeup_timeout))) {
dev_err(wdev->dev, "chip didn't wake up. Chip wasn't reset?\n"); return -ETIMEDOUT;
}
}
dev_dbg(wdev->dev, "chip wake up after %lldus\n", ktime_us_delta(now, start));
ret = wfx_config_reg_write_bits(wdev, CFG_CPU_RESET, 0); if (ret < 0) return ret;
ret = load_firmware_secure(wdev); if (ret < 0) return ret; return wfx_config_reg_write_bits(wdev,
CFG_DIRECT_ACCESS_MODE |
CFG_IRQ_ENABLE_DATA |
CFG_IRQ_ENABLE_WRDY,
CFG_IRQ_ENABLE_DATA);
}
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.