123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- /*
- * dfu.c -- DFU back-end routines
- *
- * Copyright (C) 2012 Samsung Electronics
- * author: Lukasz Majewski <l.majewski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <common.h>
- #include <malloc.h>
- #include <errno.h>
- #include <dfu.h>
- enum dfu_mmc_op {
- DFU_OP_READ = 1,
- DFU_OP_WRITE,
- };
- static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
- void *buf, long *len)
- {
- char cmd_buf[DFU_CMD_BUF_SIZE];
- sprintf(cmd_buf, "mmc %s 0x%x %x %x",
- op == DFU_OP_READ ? "read" : "write",
- (unsigned int) buf,
- dfu->data.mmc.lba_start,
- dfu->data.mmc.lba_size);
- if (op == DFU_OP_READ)
- *len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size;
- debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
- return run_command(cmd_buf, 0);
- }
- static inline int mmc_block_write(struct dfu_entity *dfu, void *buf, long *len)
- {
- return mmc_block_op(DFU_OP_WRITE, dfu, buf, len);
- }
- static inline int mmc_block_read(struct dfu_entity *dfu, void *buf, long *len)
- {
- return mmc_block_op(DFU_OP_READ, dfu, buf, len);
- }
- static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
- void *buf, long *len)
- {
- char cmd_buf[DFU_CMD_BUF_SIZE];
- char *str_env;
- int ret;
- switch (dfu->layout) {
- case DFU_FS_FAT:
- sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s %lx",
- op == DFU_OP_READ ? "load" : "write",
- dfu->data.mmc.dev, dfu->data.mmc.part,
- (unsigned int) buf, dfu->name, *len);
- break;
- case DFU_FS_EXT4:
- sprintf(cmd_buf, "ext4%s mmc %d:%d /%s 0x%x %ld",
- op == DFU_OP_READ ? "load" : "write",
- dfu->data.mmc.dev, dfu->data.mmc.part,
- dfu->name, (unsigned int) buf, *len);
- break;
- default:
- printf("%s: Layout (%s) not (yet) supported!\n", __func__,
- dfu_get_layout(dfu->layout));
- }
- debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
- ret = run_command(cmd_buf, 0);
- if (ret) {
- puts("dfu: Read error!\n");
- return ret;
- }
- if (dfu->layout != DFU_RAW_ADDR && op == DFU_OP_READ) {
- str_env = getenv("filesize");
- if (str_env == NULL) {
- puts("dfu: Wrong file size!\n");
- return -1;
- }
- *len = simple_strtoul(str_env, NULL, 16);
- }
- return ret;
- }
- static inline int mmc_file_write(struct dfu_entity *dfu, void *buf, long *len)
- {
- return mmc_file_op(DFU_OP_WRITE, dfu, buf, len);
- }
- static inline int mmc_file_read(struct dfu_entity *dfu, void *buf, long *len)
- {
- return mmc_file_op(DFU_OP_READ, dfu, buf, len);
- }
- int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
- {
- int ret = -1;
- switch (dfu->layout) {
- case DFU_RAW_ADDR:
- ret = mmc_block_write(dfu, buf, len);
- break;
- case DFU_FS_FAT:
- case DFU_FS_EXT4:
- ret = mmc_file_write(dfu, buf, len);
- break;
- default:
- printf("%s: Layout (%s) not (yet) supported!\n", __func__,
- dfu_get_layout(dfu->layout));
- }
- return ret;
- }
- int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
- {
- int ret = -1;
- switch (dfu->layout) {
- case DFU_RAW_ADDR:
- ret = mmc_block_read(dfu, buf, len);
- break;
- case DFU_FS_FAT:
- case DFU_FS_EXT4:
- ret = mmc_file_read(dfu, buf, len);
- break;
- default:
- printf("%s: Layout (%s) not (yet) supported!\n", __func__,
- dfu_get_layout(dfu->layout));
- }
- return ret;
- }
- int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
- {
- int dev, part;
- struct mmc *mmc;
- block_dev_desc_t *blk_dev;
- disk_partition_t partinfo;
- char *st;
- dfu->dev_type = DFU_DEV_MMC;
- st = strsep(&s, " ");
- if (!strcmp(st, "mmc")) {
- dfu->layout = DFU_RAW_ADDR;
- dfu->data.mmc.lba_start = simple_strtoul(s, &s, 16);
- dfu->data.mmc.lba_size = simple_strtoul(++s, &s, 16);
- dfu->data.mmc.lba_blk_size = get_mmc_blk_size(dfu->dev_num);
- } else if (!strcmp(st, "fat")) {
- dfu->layout = DFU_FS_FAT;
- } else if (!strcmp(st, "ext4")) {
- dfu->layout = DFU_FS_EXT4;
- } else if (!strcmp(st, "part")) {
- dfu->layout = DFU_RAW_ADDR;
- dev = simple_strtoul(s, &s, 10);
- s++;
- part = simple_strtoul(s, &s, 10);
- mmc = find_mmc_device(dev);
- if (mmc == NULL || mmc_init(mmc)) {
- printf("%s: could not find mmc device #%d!\n", __func__, dev);
- return -ENODEV;
- }
- blk_dev = &mmc->block_dev;
- if (get_partition_info(blk_dev, part, &partinfo) != 0) {
- printf("%s: could not find partition #%d on mmc device #%d!\n",
- __func__, part, dev);
- return -ENODEV;
- }
- dfu->data.mmc.lba_start = partinfo.start;
- dfu->data.mmc.lba_size = partinfo.size;
- dfu->data.mmc.lba_blk_size = partinfo.blksz;
- } else {
- printf("%s: Memory layout (%s) not supported!\n", __func__, st);
- return -ENODEV;
- }
- if (dfu->layout == DFU_FS_EXT4 || dfu->layout == DFU_FS_FAT) {
- dfu->data.mmc.dev = simple_strtoul(s, &s, 10);
- dfu->data.mmc.part = simple_strtoul(++s, &s, 10);
- }
- dfu->read_medium = dfu_read_medium_mmc;
- dfu->write_medium = dfu_write_medium_mmc;
- return 0;
- }
|