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); } }
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; }
/* * 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; }
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(""); }
/* 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); }
/* * 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; }
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; }