Skip to main content

加载固件

驱动位于 kernel/linux-4.9/drivers/remoteproc/sunxi_rproc_firmware.c

首先调用 sunxi_request_firmware 函数

int sunxi_request_firmware(const struct firmware **fw, const char *name, struct device *dev)
{
int ret, index;
struct firmware *fw_p = NULL;
u32 img_addr, img_len;

ret = sunxi_find_firmware_storage();
if (ret < 0) {
dev_warn(dev, "Can't finded boot_package head\n");
return -ENODEV;
}

index = ret;

ret = sunxi_firmware_get_info(dev, index, name, &img_addr, &img_len);
if (ret < 0) {
dev_warn(dev, "failed to read boot_package item\n");
ret = -EFAULT;
goto out;
}

ret = sunxi_firmware_get_data(dev, index, img_addr, img_len, &fw_p);
if (ret < 0) {
dev_err(dev, "failed to read Firmware\n");
ret = -ENOMEM;
goto out;
}

*fw = fw_p;
out:
return ret;
}

驱动会从固件的特定位置读取,使用函数 sunxi_find_firmware_storage,这里会去固定的位置查找固件,位置包括 lib/firmware/dev/mtd0. /dev/mtd1, /dev/mmcblk0 等位置。对于Linux启动我们只需要放置于 lib/firmware 即可。

static int sunxi_find_firmware_storage(void)
{
struct firmware_head_info *head;
int i, len, ret;
loff_t pos;
const char *path;
u32 flag;

len = sizeof(*head);
head = kmalloc(len, GFP_KERNEL);
if (!head)
return -ENOMEM;

ret = sunxi_get_storage_type();

for (i = 0; i < ARRAY_SIZE(firmware_storages); i++) {
path = firmware_storages[i].path;
pos = firmware_storages[i].head_off;
flag = firmware_storages[i].flag;

if (flag != ret)
continue;

pr_debug("try to open %s\n", path);

ret = sunxi_firmware_read(path, head, len, &pos, flag);
if (ret < 0)
pr_err("open %s failed,ret=%d\n", path, ret);

if (ret != len)
continue;

if (head->magic == FIRMWARE_MAGIC) {
kfree(head);
return i;
}
}

kfree(head);

return -ENODEV;
}