1cb383cd2SLukasz Majewski /* 2cb383cd2SLukasz Majewski * dfu.c -- DFU back-end routines 3cb383cd2SLukasz Majewski * 4cb383cd2SLukasz Majewski * Copyright (C) 2012 Samsung Electronics 5cb383cd2SLukasz Majewski * author: Lukasz Majewski <l.majewski@samsung.com> 6cb383cd2SLukasz Majewski * 7cb383cd2SLukasz Majewski * This program is free software; you can redistribute it and/or modify 8cb383cd2SLukasz Majewski * it under the terms of the GNU General Public License as published by 9cb383cd2SLukasz Majewski * the Free Software Foundation; either version 2 of the License, or 10cb383cd2SLukasz Majewski * (at your option) any later version. 11cb383cd2SLukasz Majewski * 12cb383cd2SLukasz Majewski * This program is distributed in the hope that it will be useful, 13cb383cd2SLukasz Majewski * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cb383cd2SLukasz Majewski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15cb383cd2SLukasz Majewski * GNU General Public License for more details. 16cb383cd2SLukasz Majewski * 17cb383cd2SLukasz Majewski * You should have received a copy of the GNU General Public License 18cb383cd2SLukasz Majewski * along with this program; if not, write to the Free Software 19cb383cd2SLukasz Majewski * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20cb383cd2SLukasz Majewski */ 21cb383cd2SLukasz Majewski 22cb383cd2SLukasz Majewski #include <common.h> 23cb383cd2SLukasz Majewski #include <malloc.h> 24cb383cd2SLukasz Majewski #include <dfu.h> 25cb383cd2SLukasz Majewski 26cb383cd2SLukasz Majewski enum dfu_mmc_op { 27cb383cd2SLukasz Majewski DFU_OP_READ = 1, 28cb383cd2SLukasz Majewski DFU_OP_WRITE, 29cb383cd2SLukasz Majewski }; 30cb383cd2SLukasz Majewski 31cb383cd2SLukasz Majewski static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu, 32cb383cd2SLukasz Majewski void *buf, long *len) 33cb383cd2SLukasz Majewski { 34cb383cd2SLukasz Majewski char cmd_buf[DFU_CMD_BUF_SIZE]; 35cb383cd2SLukasz Majewski 36cb383cd2SLukasz Majewski sprintf(cmd_buf, "mmc %s 0x%x %x %x", 37cb383cd2SLukasz Majewski op == DFU_OP_READ ? "read" : "write", 38cb383cd2SLukasz Majewski (unsigned int) buf, 39cb383cd2SLukasz Majewski dfu->data.mmc.lba_start, 40cb383cd2SLukasz Majewski dfu->data.mmc.lba_size); 41cb383cd2SLukasz Majewski 42cb383cd2SLukasz Majewski if (op == DFU_OP_READ) 43cb383cd2SLukasz Majewski *len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size; 44cb383cd2SLukasz Majewski 45cb383cd2SLukasz Majewski debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf); 46cb383cd2SLukasz Majewski return run_command(cmd_buf, 0); 47cb383cd2SLukasz Majewski } 48cb383cd2SLukasz Majewski 49cb383cd2SLukasz Majewski static inline int mmc_block_write(struct dfu_entity *dfu, void *buf, long *len) 50cb383cd2SLukasz Majewski { 51cb383cd2SLukasz Majewski return mmc_block_op(DFU_OP_WRITE, dfu, buf, len); 52cb383cd2SLukasz Majewski } 53cb383cd2SLukasz Majewski 54cb383cd2SLukasz Majewski static inline int mmc_block_read(struct dfu_entity *dfu, void *buf, long *len) 55cb383cd2SLukasz Majewski { 56cb383cd2SLukasz Majewski return mmc_block_op(DFU_OP_READ, dfu, buf, len); 57cb383cd2SLukasz Majewski } 58cb383cd2SLukasz Majewski 59cb383cd2SLukasz Majewski static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu, 60cb383cd2SLukasz Majewski void *buf, long *len) 61cb383cd2SLukasz Majewski { 62cb383cd2SLukasz Majewski char cmd_buf[DFU_CMD_BUF_SIZE]; 63cb383cd2SLukasz Majewski char *str_env; 64cb383cd2SLukasz Majewski int ret; 65cb383cd2SLukasz Majewski 66*43e66272SŁukasz Majewski switch (dfu->layout) { 67*43e66272SŁukasz Majewski case DFU_FS_FAT: 68cb383cd2SLukasz Majewski sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s %lx", 69cb383cd2SLukasz Majewski op == DFU_OP_READ ? "load" : "write", 70cb383cd2SLukasz Majewski dfu->data.mmc.dev, dfu->data.mmc.part, 71cb383cd2SLukasz Majewski (unsigned int) buf, dfu->name, *len); 72*43e66272SŁukasz Majewski break; 73*43e66272SŁukasz Majewski case DFU_FS_EXT4: 74*43e66272SŁukasz Majewski sprintf(cmd_buf, "ext4%s mmc %d:%d /%s 0x%x %ld", 75*43e66272SŁukasz Majewski op == DFU_OP_READ ? "load" : "write", 76*43e66272SŁukasz Majewski dfu->data.mmc.dev, dfu->data.mmc.part, 77*43e66272SŁukasz Majewski dfu->name, (unsigned int) buf, *len); 78*43e66272SŁukasz Majewski break; 79*43e66272SŁukasz Majewski default: 80*43e66272SŁukasz Majewski printf("%s: Layout (%s) not (yet) supported!\n", __func__, 81*43e66272SŁukasz Majewski dfu_get_layout(dfu->layout)); 82*43e66272SŁukasz Majewski } 83cb383cd2SLukasz Majewski 84cb383cd2SLukasz Majewski debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf); 85cb383cd2SLukasz Majewski 86cb383cd2SLukasz Majewski ret = run_command(cmd_buf, 0); 87cb383cd2SLukasz Majewski if (ret) { 88cb383cd2SLukasz Majewski puts("dfu: Read error!\n"); 89cb383cd2SLukasz Majewski return ret; 90cb383cd2SLukasz Majewski } 91cb383cd2SLukasz Majewski 92cb383cd2SLukasz Majewski if (dfu->layout != DFU_RAW_ADDR) { 93cb383cd2SLukasz Majewski str_env = getenv("filesize"); 94cb383cd2SLukasz Majewski if (str_env == NULL) { 95cb383cd2SLukasz Majewski puts("dfu: Wrong file size!\n"); 96cb383cd2SLukasz Majewski return -1; 97cb383cd2SLukasz Majewski } 98cb383cd2SLukasz Majewski *len = simple_strtoul(str_env, NULL, 16); 99cb383cd2SLukasz Majewski } 100cb383cd2SLukasz Majewski 101cb383cd2SLukasz Majewski return ret; 102cb383cd2SLukasz Majewski } 103cb383cd2SLukasz Majewski 104cb383cd2SLukasz Majewski static inline int mmc_file_write(struct dfu_entity *dfu, void *buf, long *len) 105cb383cd2SLukasz Majewski { 106cb383cd2SLukasz Majewski return mmc_file_op(DFU_OP_WRITE, dfu, buf, len); 107cb383cd2SLukasz Majewski } 108cb383cd2SLukasz Majewski 109cb383cd2SLukasz Majewski static inline int mmc_file_read(struct dfu_entity *dfu, void *buf, long *len) 110cb383cd2SLukasz Majewski { 111cb383cd2SLukasz Majewski return mmc_file_op(DFU_OP_READ, dfu, buf, len); 112cb383cd2SLukasz Majewski } 113cb383cd2SLukasz Majewski 114cb383cd2SLukasz Majewski int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len) 115cb383cd2SLukasz Majewski { 116cb383cd2SLukasz Majewski int ret = -1; 117cb383cd2SLukasz Majewski 118cb383cd2SLukasz Majewski switch (dfu->layout) { 119cb383cd2SLukasz Majewski case DFU_RAW_ADDR: 120cb383cd2SLukasz Majewski ret = mmc_block_write(dfu, buf, len); 121cb383cd2SLukasz Majewski break; 122cb383cd2SLukasz Majewski case DFU_FS_FAT: 123*43e66272SŁukasz Majewski case DFU_FS_EXT4: 124cb383cd2SLukasz Majewski ret = mmc_file_write(dfu, buf, len); 125cb383cd2SLukasz Majewski break; 126cb383cd2SLukasz Majewski default: 127cb383cd2SLukasz Majewski printf("%s: Layout (%s) not (yet) supported!\n", __func__, 128cb383cd2SLukasz Majewski dfu_get_layout(dfu->layout)); 129cb383cd2SLukasz Majewski } 130cb383cd2SLukasz Majewski 131cb383cd2SLukasz Majewski return ret; 132cb383cd2SLukasz Majewski } 133cb383cd2SLukasz Majewski 134cb383cd2SLukasz Majewski int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len) 135cb383cd2SLukasz Majewski { 136cb383cd2SLukasz Majewski int ret = -1; 137cb383cd2SLukasz Majewski 138cb383cd2SLukasz Majewski switch (dfu->layout) { 139cb383cd2SLukasz Majewski case DFU_RAW_ADDR: 140cb383cd2SLukasz Majewski ret = mmc_block_read(dfu, buf, len); 141cb383cd2SLukasz Majewski break; 142cb383cd2SLukasz Majewski case DFU_FS_FAT: 143*43e66272SŁukasz Majewski case DFU_FS_EXT4: 144cb383cd2SLukasz Majewski ret = mmc_file_read(dfu, buf, len); 145cb383cd2SLukasz Majewski break; 146cb383cd2SLukasz Majewski default: 147cb383cd2SLukasz Majewski printf("%s: Layout (%s) not (yet) supported!\n", __func__, 148cb383cd2SLukasz Majewski dfu_get_layout(dfu->layout)); 149cb383cd2SLukasz Majewski } 150cb383cd2SLukasz Majewski 151cb383cd2SLukasz Majewski return ret; 152cb383cd2SLukasz Majewski } 153cb383cd2SLukasz Majewski 154cb383cd2SLukasz Majewski int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s) 155cb383cd2SLukasz Majewski { 156cb383cd2SLukasz Majewski char *st; 157cb383cd2SLukasz Majewski 158cb383cd2SLukasz Majewski dfu->dev_type = DFU_DEV_MMC; 159cb383cd2SLukasz Majewski st = strsep(&s, " "); 160cb383cd2SLukasz Majewski if (!strcmp(st, "mmc")) { 161cb383cd2SLukasz Majewski dfu->layout = DFU_RAW_ADDR; 162cb383cd2SLukasz Majewski dfu->data.mmc.lba_start = simple_strtoul(s, &s, 16); 163cb383cd2SLukasz Majewski dfu->data.mmc.lba_size = simple_strtoul(++s, &s, 16); 164cb383cd2SLukasz Majewski dfu->data.mmc.lba_blk_size = get_mmc_blk_size(dfu->dev_num); 165cb383cd2SLukasz Majewski } else if (!strcmp(st, "fat")) { 166cb383cd2SLukasz Majewski dfu->layout = DFU_FS_FAT; 167*43e66272SŁukasz Majewski } else if (!strcmp(st, "ext4")) { 168*43e66272SŁukasz Majewski dfu->layout = DFU_FS_EXT4; 169cb383cd2SLukasz Majewski } else { 170cb383cd2SLukasz Majewski printf("%s: Memory layout (%s) not supported!\n", __func__, st); 171cb383cd2SLukasz Majewski } 172cb383cd2SLukasz Majewski 173*43e66272SŁukasz Majewski if (dfu->layout == DFU_FS_EXT4 || dfu->layout == DFU_FS_FAT) { 174*43e66272SŁukasz Majewski dfu->data.mmc.dev = simple_strtoul(s, &s, 10); 175*43e66272SŁukasz Majewski dfu->data.mmc.part = simple_strtoul(++s, &s, 10); 176*43e66272SŁukasz Majewski } 177*43e66272SŁukasz Majewski 178cb383cd2SLukasz Majewski dfu->read_medium = dfu_read_medium_mmc; 179cb383cd2SLukasz Majewski dfu->write_medium = dfu_write_medium_mmc; 180cb383cd2SLukasz Majewski 181cb383cd2SLukasz Majewski return 0; 182cb383cd2SLukasz Majewski } 183