Exemple #1
0
int usb_boot(struct usb_device *usbdev, u16 pid)
{
	int i, ret = 0;
	struct file *filp = NULL;
	struct inode *inode = NULL;
	static mm_segment_t fs;
	struct img_header hdr;
	struct fw_info fw_info;
	loff_t pos = 0;
	char *img_name = UIMG_PATH;
	int len;

	tx_buf = (u8 *)kmalloc(DOWNLOAD_SIZE, GFP_KERNEL);
	if (tx_buf == NULL) {
		printk(KERN_ERR "Error: kmalloc\n");
		return -ENOMEM;
	}

	fs = get_fs();
	set_fs(get_ds());

	filp = filp_open(img_name, O_RDONLY | O_LARGEFILE, 0);
	if (IS_ERR(filp)) {
		printk(KERN_ERR "Can't find %s.\n", img_name);
		set_fs(fs);
		ret = -ENOENT;
		goto restore_fs;
	}

	if (filp->f_dentry)
		inode = filp->f_dentry->d_inode;
	if (!inode || !S_ISREG(inode->i_mode)) {
		printk(KERN_ERR "Invalid file type: %s\n", img_name);
		ret = -EINVAL;
		goto out;
	}

	len = filp->f_op->read(filp, (u8 *)&hdr, sizeof(hdr), &pos);
	if (len != sizeof(hdr)) {
		printk(KERN_ERR "gdmwm: Cannot read the image info.\n");
		ret = -EIO;
		goto out;
	}

	array_le32_to_cpu((u32 *)&hdr, 19);
#if 0
	if (hdr.magic_code != 0x10767fff) {
		printk(KERN_ERR "gdmwm: Invalid magic code 0x%08x\n", hdr.magic_code);
		ret = -EINVAL;
		goto out;
	}
#endif
	if (hdr.count > MAX_IMG_CNT) {
		printk(KERN_ERR "gdmwm: Too many images. %d\n", hdr.count);
		ret = -EINVAL;
		goto out;
	}

	for (i = 0; i < hdr.count; i++) {
		if (hdr.offset[i] > hdr.len) {
			printk(KERN_ERR "gdmwm: Invalid offset. Entry = %d Offset = 0x%08x Image length = 0x%08x\n", i, hdr.offset[i], hdr.len);
			ret = -EINVAL;
			goto out;
		}

		pos = hdr.offset[i];
		len = filp->f_op->read(filp, (u8 *)&fw_info, sizeof(fw_info), &pos);
		if (len != sizeof(fw_info)) {
			printk(KERN_ERR "gdmwm: Cannot read the FW info.\n");
			ret = -EIO;
			goto out;
		}

		array_le32_to_cpu((u32 *)&fw_info, 8);
#if 0
		if ((fw_info.id & 0xfffff000) != 0x10767000) {
			printk(KERN_ERR "gdmwm: Invalid FW id. 0x%08x\n", fw_info.id);
			ret = -EIO;
			goto out;
		}
#endif

		if ((fw_info.id & 0xffff) != pid)
			continue;

		pos = hdr.offset[i] + fw_info.kernel_offset;
		ret = download_image(usbdev, filp, &pos, fw_info.kernel_len,
				DN_KERNEL_MAGIC_NUMBER);
		if (ret < 0)
			goto out;
		printk("GCT: Kernel download success.\n");

		pos = hdr.offset[i] + fw_info.rootfs_offset;
		ret = download_image(usbdev, filp, &pos, fw_info.rootfs_len,
				DN_ROOTFS_MAGIC_NUMBER);
		if (ret < 0)
			goto out;
		printk("GCT: Filesystem download success.\n");

		break;
	}

	if (i == hdr.count) {
		printk(KERN_ERR "Firmware for gsk%x is not installed.\n", pid);
		ret = -EINVAL;
	}
out:
	filp_close(filp, current->files);

restore_fs:
	set_fs(fs);
	kfree(tx_buf);
	return ret;
}
Exemple #2
0
int usb_boot(struct usb_device *usbdev, u16 pid)
{
	int i, ret = 0;
	struct img_header hdr;
	struct fw_info fw_info;
	loff_t pos = 0;
	char *img_name = FW_DIR FW_UIMG;
	const struct firmware *firm;

	ret = request_firmware(&firm, img_name, &usbdev->dev);
	if (ret < 0) {
		dev_err(&usbdev->dev,
			"requesting firmware %s failed with error %d\n",
			img_name, ret);
		return ret;
	}

	tx_buf = kmalloc(DOWNLOAD_SIZE, GFP_KERNEL);
	if (tx_buf == NULL)
		return -ENOMEM;

	if (firm->size < sizeof(hdr)) {
		dev_err(&usbdev->dev, "Cannot read the image info.\n");
		ret = -EIO;
		goto out;
	}
	memcpy(&hdr, firm->data, sizeof(hdr));

	array_le32_to_cpu((u32 *)&hdr, 19);

	if (hdr.count > MAX_IMG_CNT) {
		dev_err(&usbdev->dev, "Too many images. %d\n", hdr.count);
		ret = -EINVAL;
		goto out;
	}

	for (i = 0; i < hdr.count; i++) {
		if (hdr.offset[i] > hdr.len) {
			dev_err(&usbdev->dev,
				"Invalid offset. Entry = %d Offset = 0x%08x Image length = 0x%08x\n",
				i, hdr.offset[i], hdr.len);
			ret = -EINVAL;
			goto out;
		}

		pos = hdr.offset[i];
		if (firm->size < sizeof(fw_info) + pos) {
			dev_err(&usbdev->dev, "Cannot read the FW info.\n");
			ret = -EIO;
			goto out;
		}
		memcpy(&fw_info, firm->data + pos, sizeof(fw_info));

		array_le32_to_cpu((u32 *)&fw_info, 8);

		if ((fw_info.id & 0xffff) != pid)
			continue;

		pos = hdr.offset[i] + fw_info.kernel_offset;
		if (firm->size < fw_info.kernel_len + pos) {
			dev_err(&usbdev->dev, "Kernel FW is too small.\n");
			goto out;
		}

		ret = download_image(usbdev, firm, pos, fw_info.kernel_len,
				     DN_KERNEL_MAGIC_NUMBER);
		if (ret < 0)
			goto out;
		dev_info(&usbdev->dev, "GCT: Kernel download success.\n");

		pos = hdr.offset[i] + fw_info.rootfs_offset;
		if (firm->size < fw_info.rootfs_len + pos) {
			dev_err(&usbdev->dev, "Filesystem FW is too small.\n");
			goto out;
		}
		ret = download_image(usbdev, firm, pos, fw_info.rootfs_len,
				     DN_ROOTFS_MAGIC_NUMBER);
		if (ret < 0)
			goto out;
		dev_info(&usbdev->dev, "GCT: Filesystem download success.\n");

		break;
	}

	if (i == hdr.count) {
		dev_err(&usbdev->dev, "Firmware for gsk%x is not installed.\n",
			pid);
		ret = -EINVAL;
	}
out:
	release_firmware(firm);
	kfree(tx_buf);
	return ret;
}