예제 #1
0
파일: fb_mmc.c 프로젝트: LinuxOfLyp/u-boot
void fb_mmc_flash_write(const char *cmd, void *download_buffer,
			unsigned int download_bytes)
{
	struct blk_desc *dev_desc;
	disk_partition_t info;

	dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
	if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
		error("invalid mmc device\n");
		fastboot_fail("invalid mmc device");
		return;
	}

	if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
		printf("%s: updating MBR, Primary and Backup GPT(s)\n",
		       __func__);
		if (is_valid_gpt_buf(dev_desc, download_buffer)) {
			printf("%s: invalid GPT - refusing to write to flash\n",
			       __func__);
			fastboot_fail("invalid GPT partition");
			return;
		}
		if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) {
			printf("%s: writing GPT partitions failed\n", __func__);
			fastboot_fail(
				      "writing GPT partitions failed");
			return;
		}
		printf("........ success\n");
		fastboot_okay("");
		return;
	} else if (part_get_info_efi_by_name_or_alias(dev_desc, cmd, &info)) {
		error("cannot find partition: '%s'\n", cmd);
		fastboot_fail("cannot find partition");
		return;
	}

	if (is_sparse_image(download_buffer)) {
		struct fb_mmc_sparse sparse_priv;
		struct sparse_storage sparse;

		sparse_priv.dev_desc = dev_desc;

		sparse.blksz = info.blksz;
		sparse.start = info.start;
		sparse.size = info.size;
		sparse.write = fb_mmc_sparse_write;
		sparse.reserve = fb_mmc_sparse_reserve;

		printf("Flashing sparse image at offset " LBAFU "\n",
		       sparse.start);

		sparse.priv = &sparse_priv;
		write_sparse_image(&sparse, cmd, download_buffer,
				   download_bytes);
	} else {
		write_raw_image(dev_desc, &info, cmd, download_buffer,
				download_bytes);
	}
}
예제 #2
0
static int dev_stor_is_valid(int type, struct blk_desc *dd)
{
	int i;

	for (i = 0; i < specs[type].max_dev; i++)
		if (dd == blk_get_dev(specs[type].name, i))
			if (dd->type != DEV_TYPE_UNKNOWN)
				return 1;

	return 0;
}
예제 #3
0
/*
 * returns:	ENUM_IDE, ENUM_USB etc. based on struct blk_desc
 */
static int dev_stor_type(struct blk_desc *dd)
{
	int i, j;

	for (i = ENUM_IDE; i < ENUM_MAX; i++)
		for (j = 0; j < specs[i].max_dev; j++)
			if (dd == blk_get_dev(specs[i].name, j))
				return i;

	return ENUM_MAX;
}
예제 #4
0
파일: fb_mmc.c 프로젝트: LinuxOfLyp/u-boot
void fb_mmc_erase(const char *cmd)
{
	int ret;
	struct blk_desc *dev_desc;
	disk_partition_t info;
	lbaint_t blks, blks_start, blks_size, grp_size;
	struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);

	if (mmc == NULL) {
		error("invalid mmc device");
		fastboot_fail("invalid mmc device");
		return;
	}

	dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
	if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
		error("invalid mmc device");
		fastboot_fail("invalid mmc device");
		return;
	}

	ret = part_get_info_efi_by_name_or_alias(dev_desc, cmd, &info);
	if (ret) {
		error("cannot find partition: '%s'", cmd);
		fastboot_fail("cannot find partition");
		return;
	}

	/* Align blocks to erase group size to avoid erasing other partitions */
	grp_size = mmc->erase_grp_size;
	blks_start = (info.start + grp_size - 1) & ~(grp_size - 1);
	if (info.size >= grp_size)
		blks_size = (info.size - (blks_start - info.start)) &
				(~(grp_size - 1));
	else
		blks_size = 0;

	printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
	       blks_start, blks_start + blks_size);

	blks = dev_desc->block_erase(dev_desc, blks_start, blks_size);
	if (blks != blks_size) {
		error("failed erasing from device %d", dev_desc->devnum);
		fastboot_fail("failed erasing from device");
		return;
	}

	printf("........ erased " LBAFU " bytes from '%s'\n",
	       blks_size * info.blksz, cmd);
	fastboot_okay("");
}
예제 #5
0
/* usb_request complete call back to handle down load image */
static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
{
	struct f_rockusb *f_rkusb = get_rkusb();
	unsigned int transfer_size = 0;
	const unsigned char *buffer = req->buf;
	unsigned int buffer_size = req->actual;

	transfer_size = f_rkusb->dl_size - f_rkusb->dl_bytes;
	if (!f_rkusb->desc) {
		char *type = f_rkusb->dev_type;
		int index = f_rkusb->dev_index;

		f_rkusb->desc = blk_get_dev(type, index);
		if (!f_rkusb->desc ||
		    f_rkusb->desc->type == DEV_TYPE_UNKNOWN) {
			puts("invalid mmc device\n");
			rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
					     USB_BULK_CS_WRAP_LEN);
			return;
		}
	}

	if (req->status != 0) {
		printf("Bad status: %d\n", req->status);
		rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
				     USB_BULK_CS_WRAP_LEN);
		return;
	}

	if (buffer_size < transfer_size)
		transfer_size = buffer_size;

	memcpy((void *)f_rkusb->buf, buffer, transfer_size);
	f_rkusb->dl_bytes += transfer_size;
	int blks = 0, blkcnt = transfer_size  / 512;

	debug("dl %x bytes, %x blks, write lba %x, dl_size:%x, dl_bytes:%x, ",
	      transfer_size, blkcnt, f_rkusb->lba, f_rkusb->dl_size,
	      f_rkusb->dl_bytes);
	blks = blk_dwrite(f_rkusb->desc, f_rkusb->lba, blkcnt, f_rkusb->buf);
	if (blks != blkcnt) {
		printf("failed writing to device %s: %d\n", f_rkusb->dev_type,
		       f_rkusb->dev_index);
		rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
				     USB_BULK_CS_WRAP_LEN);
		return;
	}
	f_rkusb->lba += blkcnt;

	/* Check if transfer is done */
	if (f_rkusb->dl_bytes >= f_rkusb->dl_size) {
		req->complete = rx_handler_command;
		req->length = EP_BUFFER_SIZE;
		f_rkusb->buf = f_rkusb->buf_head;
		printf("transfer 0x%x bytes done\n", f_rkusb->dl_size);
		f_rkusb->dl_size = 0;
		rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_GOOD,
				     USB_BULK_CS_WRAP_LEN);
	} else {
		req->length = rx_bytes_expected(ep);
		if (f_rkusb->buf == f_rkusb->buf_head)
			f_rkusb->buf = f_rkusb->buf_head + EP_BUFFER_SIZE;
		else
			f_rkusb->buf = f_rkusb->buf_head;

		debug("remain %x bytes, %x sectors\n", req->length,
		      req->length / 512);
	}

	req->actual = 0;
	usb_ep_queue(ep, req, 0);
}
예제 #6
0
/*
 * Finds next available device in the storage group
 *
 * type:	storage group type - ENUM_IDE, ENUM_SCSI etc.
 *
 * first:	if 1 the first device in the storage group is returned (if
 *              exists), if 0 the next available device is searched
 *
 * more:	returns 0/1 depending if there are more devices in this group
 *		available (for future iterations)
 *
 * returns:	0/1 depending if device found in this iteration
 */
static int dev_stor_get(int type, int first, int *more, struct device_info *di)
{
	int found = 0;
	*more = 0;

	int i;

	struct blk_desc *dd;

	if (first) {
		di->cookie = (void *)blk_get_dev(specs[type].name, 0);
		if (di->cookie == NULL)
			return 0;
		else
			found = 1;

		/* provide hint if there are more devices in
		 * this group to enumerate */
		if (1 < specs[type].max_dev)
			*more = 1;

	} else {
		for (i = 0; i < specs[type].max_dev; i++)
			if (di->cookie ==
			    (void *)blk_get_dev(specs[type].name, i)) {
				/* previous cookie found -- advance to the
				 * next device, if possible */

				if (++i >= specs[type].max_dev) {
					/* out of range, no more to enum */
					di->cookie = NULL;
					break;
				}

				di->cookie = (void *)blk_get_dev(
							specs[type].name, i);
				if (di->cookie == NULL)
					return 0;
				else
					found = 1;

				/* provide hint if there are more devices in
				 * this group to enumerate */
				if ((i + 1) < specs[type].max_dev)
					*more = 1;

				break;
			}
	}

	if (found) {
		di->type = specs[type].type;

		if (di->cookie != NULL) {
			dd = (struct blk_desc *)di->cookie;
			if (dd->type == DEV_TYPE_UNKNOWN) {
				debugf("device instance exists, but is not active..");
				found = 0;
			} else {
				di->di_stor.block_count = dd->lba;
				di->di_stor.block_size = dd->blksz;
			}
		}

	} else
		di->cookie = NULL;

	return found;
}
예제 #7
0
파일: read.c 프로젝트: Noltari/u-boot
int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	char *ep;
	struct blk_desc *dev_desc = NULL;
	int dev;
	int part = 0;
	disk_partition_t part_info;
	ulong offset = 0u;
	ulong limit = 0u;
	void *addr;
	uint blk;
	uint cnt;

	if (argc != 6) {
		cmd_usage(cmdtp);
		return 1;
	}

	dev = (int)simple_strtoul(argv[2], &ep, 16);
	if (*ep) {
		if (*ep != ':') {
			printf("Invalid block device %s\n", argv[2]);
			return 1;
		}
		part = (int)simple_strtoul(++ep, NULL, 16);
	}

	dev_desc = blk_get_dev(argv[1], dev);
	if (dev_desc == NULL) {
		printf("Block device %s %d not supported\n", argv[1], dev);
		return 1;
	}

	addr = (void *)simple_strtoul(argv[3], NULL, 16);
	blk = simple_strtoul(argv[4], NULL, 16);
	cnt = simple_strtoul(argv[5], NULL, 16);

	if (part != 0) {
		if (part_get_info(dev_desc, part, &part_info)) {
			printf("Cannot find partition %d\n", part);
			return 1;
		}
		offset = part_info.start;
		limit = part_info.size;
	} else {
		/* Largest address not available in struct blk_desc. */
		limit = ~0;
	}

	if (cnt + blk > limit) {
		printf("Read out of range\n");
		return 1;
	}

	if (blk_dread(dev_desc, offset + blk, cnt, addr) != cnt) {
		printf("Error reading blocks\n");
		return 1;
	}

	return 0;
}